I have two user controls(A & B) placed on a particular user control(C). I want these control to come up or show only when button is clicked. I bound the visibility of A and B controls to properties but of no use. I applied styles also to hide/show but again no success.
Also I want usercontrol C to be stretched if in case both A and B controls are not visible.
Here is the usercontrol xaml where main datacontext is RunViewModelObject
<UserControl>
<UserControl.Resources>
<Style TargetType="{x:Type Control}" x:Key="RTMLOVPanel">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding LovPaneVisible, ElementName=RtmLovView, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Control}" x:Key="AttachmentPanel">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding AttachmentsPaneVisible, ElementName=AttachmentsView, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="RtmLovTemplate" x:Name="RtmLovView">
<Shared:SidePaneView_RtmLov/>
</ControlTemplate>
<ControlTemplate x:Key="AttachmentsTemplate" x:Name="AttachmentsView">
<Shared:SidePaneView_Attachments/>
</ControlTemplate>
</UserControl.Resources>
<Grid DataContext="{Binding RunViewModelObject}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0" Template="{StaticResource ResourceKey=RtmLovTemplate}"
DataContext="{Binding LovObject}" Style="{DynamicResource RTMLOVPanel}" />
<ContentControl Grid.Column="0" Template="{StaticResource ResourceKey=AttachmentsTemplate}"
DataContext="{Binding AttachmentsObject}" Style="{DynamicResource AttachmentPanel}" />
<Grid Grid.Column="1" >
<ContentControl x:Name="CCRunView" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded" >
<ContentControl.Content>
<UC:UCDynamicRunForm Visibility="{Binding DataSourceControlVisibility, Converter={StaticResource ResourceKey=BoolToOppositeVisibilityConverter}}" DataContext="{Binding UCDynamicFormVMObject}"/>
</ContentControl.Content>
</ContentControl>
</Grid>
</Grid>
</UserControl>
Related
I have an ItemsControl where I dynamically create a new GroupBox with several controls in it and model behind. That works so far. I've also implemented validation to my TextBoxes, which is also working as intended. And there is a Button to remove this GroupBox, which binds to the Ancestor of type UserControl.
<ItemsControl Grid.Row="2" ItemsSource="{Binding StorageLocationList, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<GroupBox Style="{StaticResource GroupBoxBase}">
<GroupBox.Header>
<CheckBox x:Name="ExportGroupCheckBox" Content="Storage Location active" IsChecked="{Binding GroupActive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource CheckBoxBase}" IsEnabled="{Binding ElementName=ActivateExportCheckBox, Path=IsChecked}"/>
</GroupBox.Header>
<Grid>
<Grid IsEnabled="{Binding ElementName=ExportGroupCheckBox, Path=IsChecked}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Name:" VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" Style="{StaticResource LimitedCharTextBox}" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"/>
<Label Grid.Row="1" Grid.Column="0" Content="Storage Location:" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Style="{StaticResource BaseTextBox}" Text="{Binding StorageLocationPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Browse..." VerticalAlignment="Stretch" Command="{Binding StorageLocationBrowseCommand}" Style="{StaticResource ButtonBase}"/>
</Grid>
<Canvas>
<Button Canvas.Top="0" Canvas.Right="0" Content="X" ToolTip="Remove Group" Style="{StaticResource RemoveButton}" Command="{Binding ElementName=GPUserControl, Path=DataContext.RemoveStorageLocationGroupCommand}" CommandParameter="{Binding}"/>
</Canvas>
</Grid>
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
When I now type something wrong in the TextBox that is bound to the Name property, the validation takes place and the TextBox receives a red border to indicate that. Cool. But the button to remove this GroupBox also gets a red border. And that's weird.
I also tried to set the Validation.ErrorTemplate of the Button to null like so:
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
but that sets the TextBox Validation.ErrorTemplate to null as well.
So how are they connected to each other? Somehow through the UserControl?
Here is a screenshot of it:
EDIT:
Here are the Styles:
<Style x:Key="BaseTextBox" TargetType="TextBox">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
</Trigger>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="GroupBoxBase" TargetType="GroupBox">
<Setter Property="Padding" Value="2"/>
</Style>
<Style x:Key="ConfigurationMainWindownButton" TargetType="Button">
<Setter Property="Height" Value="Auto"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Margin" Value="2,2,2,2"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<Style x:Key="RemoveButton" TargetType="Button" BasedOn="{StaticResource ConfigurationMainWindownButton}">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontWeight" Value="Bold"/>
<!-- <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/> -->
</Style>
WPF marks all your ItemsControl as not valid not only your text box inside due to using the same data model (actually model is not valid - not controls) . Text box just set state to invalid value. You could resolve it with overriding Validation.ErrorTemplate style setting for Remove Group button control if the button have to ignore validate state of model .
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<AdornedElementPlaceholder />
</ControlTemplate>
</Setter.Value>
</Setter>
I have a WPF datagrid using the WpfToolkit version 3.5.40128.1
For one cell I raise a PropertyChanged event that the viewmodel has a listener for, and determines if the value is duplicated to the other values. If it is duplicated, a state is set on the object and the cell is put into an error state.
So a user can enter Priority in the first record to 2 and the second field to 2 and the second value is in error.
When the user changes the error field all works as expected.
When the user changes the first '2' to 1 the second field is no longer duplicated and the flag is cleared. However, no matter what I do, the field remains in error. I have tried the following:
1) I added a PropertyChanged event call on the field even though it is in an ObservableCollection. This caused a regular check for duplicate values but did not remove the red outline.
2) I added event styles for both ValidationErrors==true as well as ValidationErrors==false. This sounded hopeful but it only clears the tooltip it does not clear the red outline.
3) I added a PropertyChanged call on the state boolean when it's value changes.
Playing with the field myself manually in the form, if I enter and exit the field it remains in error. If I enter the field and re-enter '2' the error state goes away.
I'm at a loss now as to what else to do! Any suggestions on additional things to try would be helpful.
Below is the style and definitions of the datagrid. Priority is the only field being validated.
<!-- style to apply to DataGrid TextBlock -->
<Style x:Key="DataGridTextBlockStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value=""/>
</Trigger>
</Style.Triggers>
</Style>
<!-- style to apply to DataGrid CheckBox -->
<Style x:Key="DataGridCheckBoxStyle" TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value=""/>
</Trigger>
</Style.Triggers>
</Style>
<!-- style to apply to DataGrid TextBox in edit mode -->
<Style x:Key="CellEditStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
<Trigger Property="Validation.HasError" Value="false">
<Setter Property="ToolTip"
Value=""/>
</Trigger>
</Style.Triggers>
</Style>
<!-- style to apply to DataGrid Checkbox in edit mode -->
<Style x:Key="CheckboxEditStyle" TargetType="{x:Type CheckBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="ToolTipService.ShowDuration"
Value="20000"/>
</Trigger>
</Style.Triggers>
</Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="345*"/>
<ColumnDefinition Width="88*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" VerticalAlignment="Top"
Margin="2,2,2,0" Header="Region Selection"
BorderBrush="White" BorderThickness="0" Grid.ColumnSpan="2">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical" Height="120"
VerticalAlignment="Top" Background="White">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Margin="5,5,5,5" Height="101" >
<wpftk:DataGrid x:Name="SegmentGrid"
IsEnabled="True"
AutoGenerateColumns="False"
VerticalScrollBarVisibility="Auto"
Height="90"
ItemsSource="{Binding SegmentList}" CanUserAddRows="False" CanUserDeleteRows="False" >
<wpftk:DataGrid.Columns>
<!-- The Region Name Column -->
<wpftk:DataGridTextColumn Header="Name"
Width="265"
Binding="{Binding RegionName}" />
<!-- The Priority Column -->
<wpftk:DataGridTemplateColumn Header="Priority" Width="60">
<wpftk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource DataGridTextBlockStyle}"
Text="{Binding Priority, Mode=TwoWay,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellTemplate>
<wpftk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox>
<TextBox.Text>
<Binding Path="Priority"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True" >
</Binding>
</TextBox.Text>
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource CellEditStyle}" />
</TextBox.Style>
</TextBox>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellEditingTemplate>
</wpftk:DataGridTemplateColumn>
<!-- The Write To Cartridge Column -->
<wpftk:DataGridTemplateColumn Header="Write To Cartridge" Width="80">
<wpftk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource DataGridCheckBoxStyle}"
IsChecked="{Binding WriteToCartridge, Mode=TwoWay,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellTemplate>
<wpftk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<CheckBox>
<CheckBox.IsChecked>
<Binding Path="WriteToCartridge"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True"
ValidatesOnExceptions="True" >
</Binding>
</CheckBox.IsChecked>
<CheckBox.Style>
<Style TargetType="CheckBox" BasedOn="{StaticResource CheckboxEditStyle}" />
</CheckBox.Style>
</CheckBox>
</DataTemplate>
</wpftk:DataGridTemplateColumn.CellEditingTemplate>
</wpftk:DataGridTemplateColumn>
</wpftk:DataGrid.Columns>
</wpftk:DataGrid>
</ScrollViewer>
</StackPanel>
</Grid>
</GroupBox>
Needed to expose a new method inside the object for INotifyPropertyChanged.
This allowed us to examine all of the objects in the array, and when we changed the value we called it from the object rather than from the viewmodel. This caused the automatic finding and clearing of any object that was duplicated within the array.
When a TextBox element has an error The custom adorner doesn't resize the StackPanel the Textbox control lies in:
Using DockPanel.Bottom causes the adorner to overlap on the Textbox below.
The code I shamelessly lifted off http://hirenkhirsaria.blogspot.ie/2013/05/wpf-input-validation-using-mvvm.html:
<ControlTemplate.Resources>
<Style x:Key="textblockErrorTooltip" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="10 0 10 0" />
</Style>
</ControlTemplate.Resources>
<DockPanel LastChildFill="true">
<Border Height="Auto" Margin="5,0,0,0" Background="#DC000C" CornerRadius="3" DockPanel.Dock="Right">
<TextBlock Style="{StaticResource textblockErrorTooltip}" Text="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
</Border>
<AdornedElementPlaceholder Name="customAdorner">
<Border BorderBrush="#DC000C" BorderThickness="1.3" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
Sure, I could use Z Index but I don't like it.
Is there a way to cause the StackPanel to resize on error?
I was thinking of adding a ContentTemplate after each Textbox control:
<StackPanel>
<TextBox/>
<ContentTemplate/>
</StackPanel>
<StackPanel>
<TextBox/>
<ContentTemplate/>
</StackPanel>
The ContentTemplate generates an error info DataTemplate which I believe should cause the StackPanel to resize.
But I can't figure out how the binding to (Validation.Errors)[0].ErrorContent} should be done.
My terrible attempt:
<UserControl.Resources>
<DataTemplate x:Key="errorinfo">
<TextBlock>Hello World</TextBlock>
</DataTemplate>
</UserControl.Resources>
<StackPanel Orientation="Horizontal" Grid.Row="4">
<Label Padding="0,0,20,0">Name:</Label>
<StackPanel>
<TextBox Padding="0,0,10,0" Width="150" x:Name="name" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
</StackPanel>
<ContentControl >
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{x:Null}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=name, Path=(Validation.HasError)}" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding ElementName=name, Path=(Validation.Errors)[0].ErrorContent}"> </TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</StackPanel>
I can't reuse the datatemplate though!
My question is similar to: WPF- Validation -The validation error message goes behind the other controls because of AdornerDecorator
I just want a different solution.
Any ideas? Thanks
Adorner layers sit separate from the main rendering layers in WPF. A good way to think of an Adorner is simply as a graphical overlay layer which encompasses the shape of the Control it's element tags surround (similar to the behaviour of a Border for example).
You don't need a separate AdornerDecorator for every Control. This means the ideal solution would be to add the AdornerDecorator at the highest level possible such as your Window so that you are always guaranteed an Adorner scope.
I can't believe it! Figured it out myself :D
<UserControl.Resources>
<Style x:Key="textblockErrorTooltip" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Margin" Value="10 0 10 0" />
</Style>
<DataTemplate x:Key="errortemplate">
<Border Height="Auto" Margin="5,0,0,0" Background="#DC000C" CornerRadius="3" DockPanel.Dock="Right">
<TextBlock Style="{StaticResource textblockErrorTooltip}" Text="{Binding Path=(Validation.Errors)[0].ErrorContent}"></TextBlock>
</Border>
</DataTemplate>
<Style x:Key="ContentControlErrorTemplate" TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{x:Null}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}, Path=Children[1].(Validation.HasError)}" Value="True">
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<Border Height="Auto" Margin="5,0,0,0" Background="#DC000C" CornerRadius="3" DockPanel.Dock="Right">
<TextBlock Style="{StaticResource textblockErrorTooltip}" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}, Path=Children[1].(Validation.Errors)[0].ErrorContent}"></TextBlock>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<StackPanel Orientation="Horizontal" Grid.Row="4">
<Label Padding="0,0,20,0">Name:</Label>
<TextBox Padding="0,0,10,0" Width="150" x:Name="name" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
<ContentControl Style="{StaticResource ContentControlErrorTemplate}">
</ContentControl>
</StackPanel>
If you have ideas to improve it please let me know. I'm not sure how efficient it is but it works.
I created a custom WPF ComboBox like this:
<ComboBox
x:Name="ComboBoxBtn"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="0,0,0,-1"
Width="300"
ItemsSource="{Binding Source, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding Path=Selected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}"
IsSynchronizedWithCurrentItem="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<ContentControl>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Favorite}" Value="True">
<Setter Property="Content">
<Setter.Value>
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="#FFE6E6FA"/>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="{Binding}" Width="250" />
<Button Grid.Column="1" Command="{Binding AddCommandButton, ElementName=root}"
CommandParameter="{Binding}">+</Button>
</Grid>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Favorite}" Value="False">
<Setter Property="Content">
<Setter.Value>
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="Yellow"/>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="{Binding}" Width="250" />
<Button Grid.Column="1" Command="{Binding RemoveCommandButton, ElementName=root}"
CommandParameter="{Binding}">-</Button>
</Grid>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The Source binding contains a ObservableColleciton where the client has a Favorite field and is supposed to show a different background and a different button. But when I open the ComboBox all the items have:
"System.Windows.Styles"
Your problem is you are setting Style as Content in the Content Control.
<ContentControl>
<Style TargetType="ContentControl">
...
</Style>
</ContentControl>
In order to set the style of the content control you should add:
<ContentControl.Style>
So the code above will look like this:
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
...
</Style>
<ContentControl.Style>
</ContentControl>
EDIT
By the way your code is very complex for the simple task of changing the background. Here is a simplified version:
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid Name="PART_GRID" Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="{Binding}"
Width="250" />
<Button Name="PART_BUTTON"
Grid.Column="1"
Content="-"
Command="{Binding AddCommandButton, ElementName=root}"
CommandParameter="{Binding}" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Favorite}"
Value="True">
<Setter TargetName="PART_GRID"
Property="Background"
Value="#FFE6E6FA" />
<Setter TargetName="PART_BUTTON"
Property="Content"
Value="+" />
<Setter TargetName="PART_BUTTON"
Property="Command"
Value="{Binding RemoveCommandButton, ElementName=root}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
In my case, I found that I had:
<ComboBox>
<Style>
</Style>
</ComboBox>
which was directly adding a style as an item, which is similar to the solution above.
I am trying to set the Grid.Column property using a datatrigger:
<Style TargetType="ListBox">
<Style.Triggers>
<DataTrigger Binding="{Binding View}" Value="HistoryLeft">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding View}" Value="HistoryRight">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Grid.ColumnSpan" Value="2"/>
</DataTrigger>
</Style.Triggers>
</Style>
The Grid.ColumnSpan works fine but the Grid.Column does not set. Any ideas?
The XAML for the Listbox is:
<ListBox ItemsSource="{Binding HistoryItemsRight}" BorderThickness="0,1,0,0" Grid.Row="0" Grid.Column="1" ItemsPanel="{StaticResource NoHorizontalScroll}" Background="White" ScrollViewer.VerticalScrollBarVisibility="Visible"
HorizontalContentAlignment="Stretch" ItemContainerStyle="{StaticResource HistoryItem}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.Style>
<Style TargetType="ListBox">
<Style.Triggers>
<DataTrigger Binding="{Binding View}" Value="HistoryLeft">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding View}" Value="HistoryRight">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Grid.ColumnSpan" Value="2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
<ListBox.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/HistoryViewTemplates.xaml"/>
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModel:HistoryItemView}">
<Grid Style="{StaticResource HistoryItemGrid}">
<Grid.ToolTip>
<controls:HistoryViewToolTip></controls:HistoryViewToolTip>
</Grid.ToolTip>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" MinWidth="30"/>
<ColumnDefinition Width="60" MinWidth="50"/>
<ColumnDefinition Width="250*" MinWidth="100"/>
</Grid.ColumnDefinitions >
<TextBlock Text="{Binding Date, StringFormat=' HH:mm:ss'}" Grid.Column="1"/>
<TextBlock Text="{Binding Path}" Grid.Column="2" HorizontalAlignment="Stretch"/>
<Button FontWeight="Bold" Padding="2,0,2,0" Margin="0,0,2,0" Width="19" Command="{Binding OperationToRight}" Grid.Column="0" Style="{StaticResource RightSideHistoryButton}" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ListBox.Resources>
</ListBox>
This might have to do with Dependency Property Value Precedence. You probably set the Column explicitly while the ColumnSpan uses the default value of one.