C# Wpf Set Costum Style to ComboBoxItem - c#

I've got a ComboBox bound to a List. The ComboBox has 3 ComboBoxItems from that list. I also got a CheckBox. If the CheckBox is unchecked and the first ComboBoxItem selected, the property "Property1" in my viewmodel is set to false. Now if "Property1" is false I'd like to change the Background and Foreground of this ComboBoxItem. How can I achieve this?
I was trying to get that done with Style and MultiDataTrigger but wasn't succesful - I only managed to change the Style for all of the ComboBoxItems and not specific one.
<Style TargetType="ComboBoxItem">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=SelectedComboBoxItem}" Value="Item1" />
<Condition Binding="{Binding Path=CheckStatus}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="GhostWhite" />
<Setter Property="Foreground" Value="Gainsboro" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
How can I achieve to change the style of a specific ComboBoxItem when its bound via List?
Thanks for your hints / help.

This is probably not the best solution, but a working one:
Instead of using a style, i created a combobox with an ItemTemplate
<ComboBox Width="200" Height="30" ItemsSource="{Binding SimpleList, UpdateSourceTrigger=PropertyChanged}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}" Background="{Binding BackGround}" Foreground="{Binding ForeGround}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
My SimpleList contains 3 "SimpleObjects" with Properties for Name, BackGround and ForeGround. BackGround is set to white and ForeGround to black by default.
Once my CheckBox is checked, I get the first Item of my List and change its properties.
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
SimpleObject obj = SimpleList.FirstOrDefault();
obj.BackGround = new SolidColorBrush(Colors.Black);
obj.ForeGround = new SolidColorBrush(Colors.White);
}
Looking like this.

Related

How to set bold in ComboBox only in presentation line, not in whole drop down list (WPF)?

I have in my DataGrid ComboBox implementation. Also I have a IsColorCalibFolderBold property by this property ComboBox know when it should represent data in bold style and when no.
So, my property
public bool IsColorCalibFolderBold
{
get { return _IsColorCalibFolderBold; }
set
{
_IsColorCalibFolderBold = value;
OnPropertyChanged();
}
}
and my .xalm
...
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
x:Name="Cb_color_calibration"
SelectionChanged="Cb_color_calibration_SelectionChanged"
ItemsSource="{Binding Path=ColorCalibrationFolders}"
SelectedItem="{Binding Path=SelectedColorCalibrationFolder}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=UIRepresentation}" />
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsColorCalibFolderBold}"
Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
...
And all is works fine here
Text is really bold when property set true and otherwise when false, but problem is here
When I open drop down list, so all items also bold... I need that only representation is bold, but dropdown list itself not.
How to make it?
I believe you need to set the ComboBox.ItemContainerStyle, so as part of the ComboBox definition:
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="FontWeight" Value="Normal"/>
</Style>
</ComboBox.ItemContainerStyle>

WPF DataGridTemplateColumn - Trigger for CheckBox IsChecked Property

I am creating a WPF DataGrid control with a DataGridTemplateColumn CheckBox which should have the IsChecked property set as true or false depending on a DataTable value)...
If the DataTable row has the value set as 1, the DataGridTemplateColumn should be true (checked). Otherwise, it will be false (unchecked)... by default, every new row will be set as true, but I couldn't bind these CheckBox rows to my DataTable value (which will be 1 or 2)
I tried the following c# code. It works when I finish the UserControl edition and loop through my DataTable to save its values... But, when I set gridResultados.ItemsSource = dataTable.DefaultView clearly not checking/unchecking my CheckBoxes because there is no binding between the DataTable column value (1 or 2) and my DataGridTemplateColumn ... this is my closest approach:
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Value?" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="True" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked">
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="Content" Value="1">
<Setter Property="IsChecked" Value="True"/>
</Trigger>
<Trigger Property="Content" Value="2">
<Setter Property="IsChecked" Value="False"/>
</Trigger>
</Style.Triggers>
</Style>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
dataTable.Rows[gridResultados.SelectedIndex].SetField(4, 1);
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
dataTable.Rows[gridResultados.SelectedIndex].SetField(4, 2);
}
Firstly I recommend you not to use DataTable in WPF, because we usually use EF in WPF, the DataTable is part of ADO.NET and it's old and nearly deprecated.
For your problems, you have somethings to fix involving the Binding and the Trigger. First the implicit DataContext in each row here is a DataRowView. It's available only for DataTrigger to use (not for Trigger). So you need to use DataTrigger instead to listen to the index [4] (which references to the fifth column - the column of CheckBox). Second the Style you set is wrong, it should be wrapped in CheckBox.Style to make it understand that you set Style for CheckBox, not for its Content. Third the Style Trigger cannot override locally set IsChecked (as in your code), in this case the template Trigger can override that, but you can also use a Style Setter to set default value True for IsChecked.
Here is the code you should have:
<DataGridTemplateColumn Header="Value?">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="IsChecked" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding [4]}" Value="1">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding [4]}" Value="2">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
<CheckBox.Style>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
BTW, I can see that you use event handler to update the value of the underlying data. But that's not the right way to go in term of MVVM where almost what you need is Binding and related stuff. However that part is yours, you need to research more on that. I think it's enough to end this problem here.

Change TextBox text and focus via CheckBox in XAML

When I check or uncheck a CheckBox, I want to clear the TextBox and set focus. I implemented it using code-behind.
My xmal:
<CheckBox x:Name="checkbox1" Checked="checkbox1_Checked" Unchecked="checkbox1_Checked" />
<TextBox x:Name="textbox1" Text="Hello" />
My C#:
private void checkbox1_Checked(object sender, RoutedEventArgs e)
{
textbox1.Text = "";
textbox1.Focus();
}
Is it possible to do it all in XAML?
Use data triggers. They work by creating a binding to a regular property, which is then
monitored for changes.
For instance, consider the following example:
<Window x:Class="WpfTutorialSamples.Styles.StyleDataTriggerSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StyleDataTriggerSample" Height="200" Width="200">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox Name="cbSample" Content="Hello, world?" />
<TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="48">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="No" />
<Setter Property="Foreground" Value="Red" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cbSample, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="Yes!" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</Window>
In this example, we have a CheckBox and a TextBlock. Using a DataTrigger, we bind the TextBlock
to the IsChecked property of the CheckBox. We then supply a default style, where the text
is "No" and the foreground colour is red, and then, using a DataTrigger, we supply a style for
when the IsChecked property of the CheckBox is changed to True, in which case we make it
green with a text saying "Yes!" (as seen on the screen shot).
you can find more in here.

StackPanel visibility depending on Combobox selection

I want to have a StackPanel who's visibility should be depending on a Combobox selection. Unfortunatly the XAML below does not work.
I found a solution with a new property which will be set on the PropertyChanged event of the Combobox selection, though I would prefer a strict XAML solution for this.
Any hints on how to solve this?
<StackPanel>
<Label>Picture in Picture function</Label>
<ComboBox Name="cbPictureInPicture" ItemsSource="{Binding Path=PictureInPictureCodeList, Mode=OneWay}" DisplayMemberPath="CodeText"
SelectedValuePath="CodeID" SelectedValue="{Binding Path=PictureInPicture, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cbPictureInPicture, Path=IsSelected.CodeText}" Value="Yes">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Label>Picture in Picture is used</Label>
(...)
</StackPanel>
you may perhaps rewrite the same as
<DataTrigger Binding="{Binding ElementName=cbPictureInPicture, Path=SelectedItem.CodeText}" Value="Yes">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
assuming the combobox is bound to a collection whose item has CodeText property. so SelectedItem.CodeText will point to the same.
additionally it may not be required to set <Setter Property="Visibility" Value="Visible" /> as it is the default value. it does not have any effect in this case just some extra line of code which can be removed.
You can also use a converter and bind directly to the PictureInPicture property:
<StackPanel Visibility="{Binding PictureInPicture, Converter={StaticResource myVisibilityConverter}}"/>
<Label>Picture in Picture is used</Label>
(...)
</StackPanel>
Create flags and pass this flag in stackpanel visibility converter.
On the basis of flag in converter make decision stackpanel visible/hide whatever
Set this flat in comboBox selection change event if selected value as per your requirement.

Datagrid and Listview with same itemssource

I have a WPF application with a DataGrid and ListView that share the same ObservableCollection ItemsSource. When the DataGrid's CanUserAddRows property is True it causes the ListView to display the extra item that the DataGrid uses to add new rows.
How can I get the extra row from the DataGrid to not show in the ListView?
I tried using a trigger on the ListView's DataTemplate and checking if the items Id was empty or 0
`<ListView.ItemTemplate>
<DataTemplate>
<Label Margin="-2,0,0,0" Name="CategoryLabel" >
<TextBlock TextWrapping="Wrap" Text="{Binding categoryName}" Height="46"></TextBlock>
</Label>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding categoryId}" Value="0" > <!-- also tried Value="" -->
<Setter TargetName="CategoryLabel" Property="Visibility" Value="Hidden" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListView.ItemTemplate>`
I just posted an answer to a problem of changing the template using a data template selector
Change View with its ViewModel based on a ViewModel Property
Possibly just because I have recently looked at this but I wonder if it might be possible to use the same technique here.
Have one template for where the category has a value,then another blank template for values without a category. The important part is you do the test in code rather than XAML so easier to inspect.
You can solve your problem without any modification of your ViewModel or code behind. You can do well without explicitly defining CollectionView's of any kind. Just add to your view's XAML one more (or only) DataTrigger that triggers on the NewItemPlaceholder item of the default view of ListView ItemsSource's collection. Have this trigger to set the UIElement.Visibility attached property to "Hidden". Place it within ItemContainerStyle style triggers. Like this:
<ListView
ItemsSource="{Binding ...}"
>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
...
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding}"
Value="{x:Static CollectionView.NewItemPlaceholder}">
<Setter Property="UIElement.Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="..." Value="{Binding ...}" />
...
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Label Margin="..." Name="...">
<TextBlock TextWrapping="Wrap"
Text="{Binding ...}" />
</Label>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>

Categories