I am working from the solution presented here, which has worked well for me until this point. I'm now trying to perform datatrigger binding to an interface property via the following XAML:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.SelectedItem).HasErrors}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.SelectedItem).HasErrors}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
When I enter this code I get a warning "The member 'SelectedItem' is not recognized or is not accessible", and I get a similar exception when I try to run. Only thing is, there is a member SelectedItem defined on the interface, and I can even navigate to it from the XAML:
public interface IChartDefinitionViewModel : IReactiveSelector<SomeClass>, IMayHaveErrors
{
// stuff
}
public interface IReactiveSelector<T> : // more stuff
{
T SelectedItem { get; set; }
}
Can anyone advise why this is happening and what I can do for a workaround? I'd like to manage this based on the interface definition or using a datatemplate for my IChartDefinitionViewModel implementation, if possible.
Update:
This also does not work, but for a different reason - when I attempt to bind to the object directly, the background doesn't change despite the fact that HasErrors toggles from true to false.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem.HasErrors}" Value="True">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem.HasErrors}" Value="False">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
There appear to have been two issues with my original post. The first is that there was a datacontext issue - thanks to James Durda for pointing this out. The row context is of type ChartDefinitionViewModel, so this code works as desired:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:ChartDefinitionViewModel.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:ChartDefinitionViewModel.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Interestingly, however, binding to the HasErrors property on the IChartDefinitionViewModel interface results in a thrown exception stating that the property path is invalid, which brings me back again to my original inquiry:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Things, however, begin to work as expected when I bind to the interface on which the HasErrors property is directly defined.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(interfaces:IMayHaveErrors.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(interfaces:IMayHaveErrors.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
I'm not sure if this is an isolated case, but it appears that WPF binding can't locate properties defined upwards in the interface inheritance hierarchy, at least in this instance.
Related
I need to hide rows under a certain condition, I do this through a style trigger. But for some reason it doesn't work if you use Map apps styles. If I delete styles from the dictionary, everything works. What i need to do to make it work with Mah app styles as well?
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsArchive}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
I also tried using baseOn but it still doesn't work
Set the RowStyle instead of ItemContainerStyle:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource MahApps.Styles.DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsArchive}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
I'm trying to set a trigger to hide my window whenever a property in my ViewModel changes. I tried using the same trigger on a different element and that worked exactly as expected, so it appears that I cannot change the visibility property of a window using a trigger. Are there any workarounds I can use to hide my window?
<Window.Style>
<Style TargetType="Window" BasedOn="{StaticResource Shell}">
<Setter Property="Visibility" Value="Hidden"/>
<Setter Property="Left" Value="{Binding SecondDisplayLeftSide}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShellType}" Value="InstructorMultiDisplay">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>
How to apply non-default Foreground color for DataGridRow when IsEnabled is set to False?
I'm doing it like this, but Foreground color is not changed.
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Name, Converter={StaticResource Converterz}}" Value="true">
<Setter Property="IsEnabled" Value="False"/>
<Setter Property="Foreground" Value="Black"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
EDIT 1
Ok, I applied style for the DataGrid.CellStyle instead of DataGrid.RowStyle and it worked, but only for cells with TextBlock's. Who can tell me why?
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}" >
<Style.Triggers>
<DataTrigger Binding="{Binding Name, Converter={StaticResource Converterz}}" Value="true">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
I currently style a DataGridRow based on the value of a column. The style looks like this;
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Overdue}" Value="1">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding Priority}" Value="High">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Priority}" Value="Medium">
<Setter Property="Background" Value="Orange"/>
</DataTrigger>
<DataTrigger Binding="{Binding Priority}" Value="Low">
<Setter Property="Background" Value="LightGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
This applies the style to the entire row based on the column's values. Now however I would to apply the style to only the columns in that cell. This is what the style currently looks like;
However I would like to remove the styling in the cells with a line through below;
i.e. only apply the formatting to the priority column's cells rather than the whole row.
You can try CellStyle for DataGridTemplateColumns.
Ref.
Like,
Add the following style "DGCellStyle" in the resource.
<Style x:Key="DGCellStyle" TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Overdue}" Value="1">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding Priority}" Value="High">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Priority}" Value="Medium">
<Setter Property="Background" Value="Orange"/>
</DataTrigger>
<DataTrigger Binding="{Binding Priority}" Value="Low">
<Setter Property="Background" Value="LightGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
Then, refer this style in DataGridTemplateColumn.
<DataGridTemplateColumn Header="ColumnHeader" Width="SizeToHeader" CellStyle="{StaticResource DGCellStyle}"/>
I'm having trouble binding the label color on my Microsoft.Windows.Controls.Ribbon.RibbonTab objects to their Enabled state.
I tried the following first:
<Style TargetType="{x:Type r:RibbonTab}">
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsEnabled}" Value="False">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
But it has no affect on the foreground. It looks like something in the ribbonTab library code is programatically overwriting the foreground.
I then tried this:
<Style x:Key="BaseRibbonTabStyle" TargetType="{x:Type r:RibbonTab}">
<EventSetter Event="IsEnabledChanged" Handler="RibbonTab_IsEnabledChanged"
</Style>
private void RibbonTab_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if( (bool)e.NewValue == false )
((RibbonTab)sender).Foreground = (new System.Windows.Media.BrushConverter()).ConvertFromString("Gray") as System.Windows.Media.Brush;
else
((RibbonTab)sender).Foreground = (new System.Windows.Media.BrushConverter()).ConvertFromString("White") as System.Windows.Media.Brush;
}
But that also failed with the following compile time error:
System.Windows.UIElement.IsEnabledChanged="RibbonTab_IsEnabledChanged_Event" is not valid. 'IsEnabledChanged' must be a RoutedEvent registered with a name that ends with the keyword "Event".
How can I get this to work?
Try a simple property trigger:
<Style TargetType="{x:Type r:RibbonTab}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</Style.Triggers>
<Setter Property="Foreground" Value="White" />
</Style>
Did you try this:
<Style TargetType="{x:Type r:RibbonTab}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsEnabled}" Value="False">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Foreground" Value="White" />
</Style>