WPF TreeView - Apply styling based on enum value - c#

I have a TreeView bound to an ObservableCollection containing enum values:
public enum Categories
{
CatA, CatB, CatC, CatD
}
public ObservableCollection<Categories> CategoriesList = new ObservableCollection<Categories>();
foreach (Categories cat in (Categories[])Enum.GetValues(typeof(Categories)))
{
CategoriesList.Add(cat);
}
The TreeView is bound to CategoriesList:
tvCat.ItemsSource = CategoriesList;
The the XAML markup:
<TreeView x:Name="tvCat">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
I am trying to figure out how to apply individual stying to TreeViewItem for each enum value, e.g. blue color for CatA, red color for CatB, may be an icon for CatC etc.
Thanks a lot for any help.

You can use DataTriggers to get the desired output.
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
<DataTrigger Binding="{Binding}" Value="CatA">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="CatB">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
EDIT
The above XAML is if you just want a different color for your Items. If you also want to have different content (e.g. an icon for CatC), then you'd have to set the ControlTemplate based on a DataTrigger.
Here is the XAML to achieve that.
<TreeView.Resources>
<ControlTemplate TargetType="TreeViewItem" x:Key="CatCTemplate">
<Image Source="icon.jpeg" Height="64" Width="64" />
</ControlTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
<DataTrigger Binding="{Binding}" Value="CatA">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="CatB">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="CatC">
<Setter Property="Template" Value="{StaticResource CatCTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>

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>

How to change font color of selected row in datagrid WPF C# when using context menu

I am developing a WPF Application using Mahapps.Metro library.
There is a DataGrid where I want to use a ContextMenu on the added rows, for that I am defining this in datagrid resources
<DataGrid.Resources>
<ContextMenu x:Key="RowMenu"
DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Borrar detalle" Click="delete_Click" />
<MenuItem Header="Editar detalle" Click="edit_Click" />
</ContextMenu>
</DataGrid.Resources>
and adding that context menu in the rowstyle
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" >
<Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
</Style>
</DataGrid.RowStyle>
The problem with this is that when user clicks on the row, it seems to disappear (the font color turns white).
I tried adding the following to the rowstyle but it does not seems to work.
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" >
<Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="LightSkyBlue"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="LightSkyBlue"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="Transparent"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
MY last option is to use the contextmenu in the grid instead rows, but I want to know if there is something I can do to make this work.
Hope you can help, thanks.
You should use based-on feature on your defined style:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
</Style>
</DataGrid.RowStyle>

Error when Styling a combo box with multiple triggers

I have a combo box to which I am trying to add some styles hence inside my Combobox. Style I am trying to set triggers for two properties but it seems like it doesn't allow me to set both properties at once. The code I am having trouble is below
The error displayed says Property elements cannot be in the middle of an element's content. They must be before or after the content
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="..." />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="..." />
</Trigger>
</Style.Triggers>
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsExecuting}" Value="False">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
Am I writing syntactically wrong XAML here? would appreciate some help here
This compiles for me:
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="Green" />
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Blue" />
</Trigger>
<DataTrigger Binding="{Binding Path=IsExecuting}" Value="False">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
All I did was made sure there is only one Style.Triggers

Disable row selection datagrid WPF when a property is set to a value

I want to disable row selection if a property is set to a value
I tried:
<DataGrid ...>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsBusy}" Value="True">
<Setter Property="here I don't know" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
I don't want to disable entire DataGrid because horizontal scroll is not scrollable anymore, so I avoid this.
If you want to unselect the entire row, try with a RowStyle instead and set the property IsSelected to false when your your data trigger is true:
<DataGrid>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Setter Property="Foreground" Value="Black" />
<DataTrigger Binding="{Binding Path=IsBusy}" Value="True">
<Setter Property="IsSelected" Value="False" />
</DataTrigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Foreground" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>

DatagridRow IsSelected not totally working

I'm currently on the design of my application (WPF), and I'm trying to change the design of the IsSelected of DatagridRow.
The XAML :
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{StaticResource ForegroundSelectedRow}"/>
<Setter Property="Background" Value="{StaticResource BackgroundSelectedRow}"/>
</Trigger>
</Style.Triggers>
</Style>
This code is working when I've the focus on my application, but when I click out of the view with the DataGrid, I lose the Foreground (it takes another color) but the Background is still up with the same...
I don't understand how just one can work, but not the other... Someone knows why ?
EDIT 1 :
I don't have any DataGrid.Resources. I set all my style in the App.xaml with this :
<Style x:Key="DataGridStyle" TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="AlternationCount" Value="2"/>
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="CanUserSortColumns" Value="True"/>
<Setter Property="CanUserAddRows" Value="False"/>
</Style>
And I bind it to my DataGrid
<DataGrid ItemsSource="{Binding Collects}" Style="{StaticResource DataGridStyle}" ColumnHeaderStyle="{StaticResource DGHeaderMargin}"/>
You can change TargedType to DataGridCell instead DataGridRow (WPF 4.0)
<DataGrid.Resources>
<Style TargetType="{x:Type dg:DataGridCell}">
<Style.Triggers>
<Trigger Property="dg:DataGridCell.IsSelected" Value="True">
<Setter Property="Foreground" Value="{StaticResource ForegroundSelectedRow}"/>
<Setter Property="Background" Value="{StaticResource BackgroundSelectedRow}"/>
</Trigger>
</Style.Triggers>
</Style>
solution 2
<DataGrid.Resources>
<Style TargetType="DataGridRow">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
</Style.Resources>
</Style>
</DataGrid.Resources>
Thanks to M. Wiśnicki, I figured out !
If you want to have a properly design, you have to apply style on DataGridRow and DataGridCell, like this :
<Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{StaticResource ForegroundSelectedRow}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource BackgroundSelectedRow}"/>
</Trigger>
</Style.Triggers>
</Style>
I hope it will help some others developers :)

Categories

Resources