Usage of ContentTemplate follow to InvalidOperationException - c#

I have a dialog that can show information in different way. To achive that I use a ContentTemplate and DataTemplates. But I am getting some error when I try to define what DataTemplate should be used. I am doing the following:
<ContentControl Content="{Binding}" >
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding UseImageTemplate}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource ImageTemplate}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding UseMessageTemplate}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource MessageTemplate}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding UseImageMessageTemplate}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource ImageMessageTemplate}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
And the definition of DataTemplates are like this:
<DataTemplate x:Key="ImageTemplate">
<Grid>
<Image Source="{Binding Image}" Stretch="Uniform" Width="48" Height="48"></Image>
</Grid>
</DataTemplate>
Have I forget anything? When I execute this code, I am getting an InvalidOperationException. If I don't bind the Content of the ContentControl to the DataContext, I don't get any Exception but the information of my ViewModel is not shown. Any idea?

Related

Datatrigger change property of another element

I have combobox and textbox. When I change selected item of combobox I want to change property of textbox by some conditions of combobox object and I dont know how.
Here is my code:
xaml
<ComboBox x:Name="someItems" Style="{StaticResource comboBoxItems}" />
<TextBox x:Name="myTextBox" />
app.xaml
<Style x:Key="comboBoxItems" TargetType="ComboBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ComboBoxItem">
<Style.Triggers>
<DataTrigger >
//here is missing the binding code
<Setter Property="somepropertyoftextboxobject" Value="somevalue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
<ComboBox x:Name="cBox" ItemsSource="{Binding ....}"/>
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem.SomeProperty, ElementName=cBox}"
Value="SomeValue">
<!--Setters for TextBox-->
<Setter Property="FontSize" Value="10"/>
<Setter Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem.SomeProperty, ElementName=cBox}"
Value="OtherValue">
<!--Setters for TextBox-->
<Setter Property="FontSize" Value="15"/>
<Setter Property="Background" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>

Change the visibility of a grid when a button has focus

I am working on a WPF application and I would like to change the visibility of a grid if an only if a button has focus. I have the following code to change the background of the button if it has focus. I know how to do this Programmatically, but I'd like to know how to get the same thing done in XAML.
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
You can name your Button and use a DataTrigger:
<Window
...
>
<Window.Resources>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=butt}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<Button x:Name="butt">Hide</Button>
<Grid>
<Label Background="Yellow">Inside Grid</Label>
</Grid>
<Button>Steal focus</Button>
</StackPanel>
</Window>
EDIT
<Window
...
>
<Window.Resources>
<Style x:Key="CollapsedGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=butt}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ToggleButton x:Name="butt">Hide</ToggleButton>
<Grid x:Name="GridA"
Style="{StaticResource CollapsedGridStyle}">
<Label Background="Yellow">Grid A</Label>
</Grid>
<Grid x:Name="GridB">
<Label Background="Green">Grid B</Label>
</Grid>
</StackPanel>
</Window>

Set DataGridCell style depending on CheckBox Checked state in DataGridTemplateColumn

I have a DataGrid with data binding to DataTable with columns set to auto generate.
The first column has boolean data type replaced with DataGridTemplateColumn with CheckBox from DataTemplate. It all works fine as it is.
However, now I want to make the DataGridCell background to red when the CheckBox is not checked.
The problem is, I have no idea how to set CheckBox's parent DataGridCell style with IsChecked trigger.
WPF:
<Window.Resources>
<DataGridTemplateColumn x:Key="colSelect">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="chkBxSelect"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsChecked="{Binding Path=Select, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Click="chkBxSelect_Click">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox x:Name="chkBxSelectAll"
Content="Select"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsThreeState="True"
Click="chkBxSelectAll_Click"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.SelectAll}">
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="DarkGray"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
</Window.Resources>
C# while DataGrid Column AutoGenerating:
DataGridTemplateColumn col = (DataGridTemplateColumn)Resources["colSelect"];
e.Column = col;
e.Column.IsReadOnly = false;
Update:
So far I have figured out it could be done using RelativeSource and AncestorType in Binding. However, still trying to make it work.
Well after struggling a lot and not even trying the most obvious solution. I found it. It was relatively very simple and easy.
Just added DataTrigger to DataGridCell style and all done, WPF is magic.
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="DarkGray"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</Trigger>
<DataTrigger Binding="{Binding Path=Select, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>

Style list item based on its property

I am pretty new to WPF and I am trying to build a quite simple application using MVVM light.
In my MainWindow.xaml (view) I have this :
<ListBox ItemsSource="{Binding InstalledVersions}"
ItemTemplate="{StaticResource VersionsDataTemplate}"
Style="{StaticResource VersionsStyle}"
ItemContainerStyle="{StaticResource VersionItemStyle}"/>
Where InstalledVersions is a list of InstalledVersionViewModel
In my MainWindowResources.xaml I have this (simplified) :
<DataTemplate x:Key="VersionsDataTemplate"
DataType="{x:Type viewmodels:InstalledVersionViewModel}">
<Grid>
<TextBlock Text="{Binding VersionNumber}" />
<TextBlock Text="{Binding FolderPath}" />
</Grid>
</DataTemplate>
<Style x:Key="VersionsStyle"
TargetType="{x:Type ListBox}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
<Style x:Key="VersionItemStyle"
TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="White" />
</Style>
I wish to have a different background depending on the "IsActive" property of my InstalledVersionViewModel.
I tried to add this (as well as several variations of it) to my VersionItemStyle but (as I suspected, mostly because I don't understand what I'm doing) it doesn't work :
<Style.Triggers>
<Trigger Property="{Binding Path=DataContext.IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewmodels:InstalledVersionViewModel}}}" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
Thanks !
Since IsActive is part of view model against each row you can achieve that with DataTrigger
<Style x:Key="VersionItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>

How to reference "PreviousData" when setting ContentPresenter.Style

In the following code I am trying to set the style of the first item in my collection to one template and the rest to a different template by checking if the PreviousElement is null. I think my relativesource is incorrect because the trigger condition is always true. What should the path be?
<DataTemplate x:Key="RowItemTemplate">
<ContentPresenter Content="{Binding}">
<ContentPresenter.Style>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="ContentTemplate" Value="{StaticResource ComparisonTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{StaticResource SourceTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Style>
</ContentPresenter>
</DataTemplate>
I created an interface that has a bool to determine which template a particular element should use:
<DataTemplate x:Key="RowItemTemplate">
<ContentPresenter Content="{Binding}">
<ContentPresenter.Style>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="ContentTemplate" Value="{StaticResource ComparisonTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding DataItem}" Value="true">
<Setter Property="ContentTemplate" Value="{StaticResource SourceTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Style>
</ContentPresenter>
</DataTemplate>

Categories

Resources