WPF: Change background on some combobox items - c#

I'm trying to change the background of certain items in a combobox that meet a condition
<ComboBox ItemsSource="{Binding Path=Model.Names, Mode=OneWay}" SelectedValue="{Binding Path=SelectedCompanyName}" DisplayMemberPath="Alias" />
The thing is that "Alias" is saved in two different places (in company and in order) and if they dont match we want to highlight this.
I want to do something like this:
<Style>...
<DataTrigger Binding="{Binding Path=isMismatch}" Value="True>
<Setter Property="Background" Value="Red" />...
Any help is appreciated.

You need to create custom data template like this:
<ComboBox Width="300" Height="30" ItemsSource="{Binding Path=Model.Names, Mode=OneWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="templateGrid">
<TextBox Text="{Binding Name}" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding isMismatch}" Value="True">
<Setter TargetName="templateGrid"
Property="Background" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

If you want to highlight the selection based on the values of two properties, I think you could use a MultiValueConverter, together with a MultiBinding.

Related

Create a ComboBox containing the values of a checked CheckBoxs

I am creating a list of CheckBoxs and a ComboBox that contains the list of checked checkboxes in WPF MVVM application. I don't know how to bind in text of combobox checked values from checkboxes.
Here is what I have tried:
<ComboBox ItemsSource="{Binding Systems}" Grid.Row="4" Grid.Column="1"
IsEditable="True" IsReadOnly="True" Text="{}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding TemplateName}" IsChecked="{Binding
IsSystemChecked, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This should do the trick:
<StackPanel>
<ListView ItemsSource="{Binding Systems}" >
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding TemplateName}" IsChecked="{Binding
IsSystemChecked, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ComboBox ItemsSource="{Binding Systems}" DisplayMemberPath="TemplateName" >
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSystemChecked}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
</ComboBox.Style>
</ComboBox>
</StackPanel>
Here there is:
ListView containing a checkbox for each item in Systems which is bound to to the IsSystemChecked property
ComboBox containing all of the items in Systems however if the IsSystemChecked property is false the Visibility is set to Collapsed so it is not displayed
Let me know if you have any issues! Hope this helps.

DataTrigger with Property = ItemControl.ItemTemplate

I Am having some trouble getting this binding to work. I have several objects within SettingCollection that all have an enum property. I want to generate a control based on what the value of this is. But when I check this value with a data trigger it does not work.
Can anyone provide some insight into how i can accomplish this?
<Window.Resources>
<DataTemplate x:Key="CheckboxNode">
<CheckBox IsChecked="{Binding Status}" Margin="0,5,0,0">
<ContentPresenter Content="{Binding DisplayName}"/>
</CheckBox>
</DataTemplate>
<DataTemplate x:Key="TextboxNode">
<TextBox Text="Badgers"></TextBox>
</DataTemplate>
</Window.Resources>
<ItemsControl ItemsSource="{Binding SettingCollection}">
<ItemsControl.Style>
<Style TargetType="ItemsControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="checkbox">
<Setter Property="ItemsControl.ItemTemplate" Value="{StaticResource CheckboxNode}" />
</DataTrigger>
<DataTrigger Binding="{Binding Type}" Value="textbox">
<Setter Property="ItemsControl.ItemTemplate" Value="{StaticResource TextboxNode}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
</ItemsControl>
If Type property is in SettingNode class, and SettingCollection is a collection of SettingNode objects, then your binding in the Datatriggers is incorrect. DataTriggers will look for Type property in ItemsControl DataContext (class with SettingCollection). Try to use DataTemplateSelector https://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector(v=vs.110).aspx

Making Templates generic

I have a WPF DataGrid that has some cells (not columns) that need to switch from readonly to editable based on some value in the viewmodel. The only way I could find to do this (after much searching) is something like this:
<UserControl.Resources>
<DataTemplate x:Key="CellTemplate">
<TextBlock
Text="{Binding MyValue}"
Style="{StaticResource CellTextBlockNumber}" />
</DataTemplate>
<DataTemplate x:Key="ReadonlyCellTemplate">
<TextBlock
Text="{Binding MyValue}"
Style="{StaticResource CellTextBlockNumberReadonly}" />
</DataTemplate>
<DataTemplate x:Key="EditableCellTemplate">
<TextBox
Text="{Binding MyValue}"
Style="{StaticResource CellTextBoxNumber}"
FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}" />
</DataTemplate>
</UserControl.Resources>
The various styles just do things like set background colors etc.
Then in the DataGrid.Columns sections:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentPresenter x:Name="Presenter" Content="{Binding}" ContentTemplate="{StaticResource CellTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding EnableCells}" Value="False">
<Setter TargetName="Presenter" Property="ContentTemplate" Value="{StaticResource ReadonlyCellTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ContentPresenter x:Name="Presenter" Content="{Binding}" ContentTemplate="{StaticResource EditableCellTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding EnableCells}" Value="False">
<Setter TargetName="Presenter" Property="ContentTemplate" Value="{StaticResource ReadonlyCellTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
So basically the ContentPresenter's ContentTemplate is being swapped out based on a DataTrigger.
This works fine for a single column, but I have about 10 columns that need this ability (at the cell level), and I really don't want to create 3 templates per column if I don't have to. Is there a way to modify this so the templates bind to a "generic" value (instead of MyValue) that I can specify at the DataGridColumn level?
Use the templates that you already have, only change is that in the text block the text should be Text="{Binding }".
Then in content control (in the cell/edit template), have the content bound like this:
Content="{Binding MyValue}"
So now you'll have only three templates and at each column you can specify a different binding for the content of the content control.

GridViewColumn with ComboBox and UserControl

I have a GridViewColumn with Combobox BAsed on ComboBox selected I want to dynamically put UI elements.Below given is the code.OperatorList has three values "Between","After","Before".Based on this selection the template has to be loaded.If "Between" Multiple TextBox else Single textbox.This part works fine.But to get the content of this and store in Model Class for each row is where i am encountering problem.
<StackPanel>
<ComboBox Grid.Column="0" ItemsSource="{Binding Path=OperatorList}" IsEditable="True"
IsSynchronizedWithCurrentItem="True"
SelectedValue="{Binding ReferenceOperatorSelected}" />
<UserControl x:Name="MyControl">
</UserControl>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding ReferenceOperatorSelected}" Value="Between">
<Setter TargetName="MyControl" Property="ContentTemplate" Value="{StaticResource MultipleTextBoxTemplate}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ReferenceOperatorSelected}" Value="After">
<Setter TargetName="MyControl" Property="ContentTemplate" Value="{StaticResource SingleTextBoxTemplate}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ReferenceOperatorSelected}" Value="Before">
<Setter TargetName="MyControl" Property="ContentTemplate" Value="{StaticResource SingleTextBoxTemplate}"></Setter>
</DataTrigger>
</DataTemplate.Triggers>
<DataTemplate x:Key="MultipleTextBoxTemplate">
<StackPanel>
<TextBox Text="{Binding Path=BetweenValue1,Mode=TwoWay,NotifyOnSourceUpdated=True}" MinWidth="40"></TextBox>
<TextBox Text="{Binding Path=BetweenValue2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" MinWidth="40"></TextBox>
</StackPanel>
</DataTemplate>
In my Model class I have two properties BetweenValue1 and BetweenVAlue2 ...These are not updated when i key in value in textboxes..
You have not set the Content for your UserControl. just try doing
<UserControl x:Name="MyControl" Content="{Binding}"/>

How can I know if item is selected inside the ItemTemplate?

I have a ListBox that use my custom ItemTemplate. I want to set Visibility property in my TextBlock (inside my template) depending on selected item. I think of doing it using triggers. But how can I know inside my template if current item is selected or not?
<DataTemplate x:Key="myTemplate">
<StackPanel Orientation="Horizontal">
<Image Tag="{Binding priority}" Loaded="SetIconPriority"/>
<Image Tag="{Binding alarm}" Loaded="SetIconAlarm"/>
<!-- I want this TextBlock to be visible only when item is selected -->
<TextBlock Text="{Binding description}"/>
</StackPanel>
</DataTemplate>
edit:
It works, thanks! Code:
<TextBlock Grid.Column="2" Grid.Row="1" Text="{Binding opis}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
Using a RelativeSource binding with AncestorType being ListBoxItem.
<DataTrigger Binding="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
(May want to reverse the logic and Collapse on False instead, avoids the default value Setter)

Categories