DataTrigger is not firing - c#

I have array of class Person in ViewModel and I want to show their names in table. I have also column with checkboxes. This is my View part:
<Grid>
<Grid.Resources>
<Style x:Key="CheckBoxStyle" TargetType="{x:Type Control}">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelectionAllowed}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ListView ItemsSource="{Binding Persons}">
<ListView.View>
<GridView>
<GridViewColumn Width="40">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource CheckBoxStyle}"
.........................
.... some logic here ....
......................./>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="140"
Header="Number"
DisplayMemberBinding="{Binding Path=Name}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
I want to show/hide checkboxes according to value of IsSelectionAllowed boolean variable. Why DataTrigger is not firing?

Assuming IsSelectionAllowed is a property on the view model set on the data context, you will need a relative source binding - hopefully this is correct without any testing:
<DataTrigger Binding="{Binding Path=IsSelectionAllowed, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
The binding of IsSelectionAllowed in your code is to the Person type.

Related

wpf Listview with buttons

I have a listview with buttons for each row, but when I bind the IsEnabled property to the SelectedIndex still keep enable all the buttons, I just need this one, and also I have another button that has to be enable depends on the property of the object in the listview.
e.g I have a class File that has a property bool HasLckFile, and I need that the download button keep disable until the user upload, but the binding is not working.
XAML:
<ListView x:Name="lv" Style="{StaticResource CustomListViewStyle}" Margin="470,0,0,0" SelectionMode="Multiple" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" >
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding Filename}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}, Path=IsSelected}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="150">
<GridViewColumn DisplayMemberBinding="{Binding Filename}"/>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="download" VerticalAlignment="Center" Click="btnDownload">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lv, Path=SelectedIndex}" Value="-1">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="upload" VerticalAlignment="Center" Click="btnUpload">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=lv, Path=SelectedIndex}" Value="-1">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>

Apply (xaml) style to DataTemplate control

I would like to apply a style, in this case of a 'ListViewItem', to a control within a DataTemplate.
Style (sample) code:
<Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="Blue" />
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="Foreground" Value="White"/>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
DataTemplate (sample) code:
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumnHeader Content="Text"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding MyImage}"/>
<Label Content="{Binding MyLabelText}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
What is the solution to apply the Background, BorderBrush and Foreground style to the <Label> within the DataTemplate?
Thank you in advance.
Note: I already read the question and answers of 'Applying style to elements inside a DataTemplate', but I would like to use xaml (so without C# code).
The following XAML styles the ListViewItem (assuming Items is your collection):
<ListView ItemsSource="{Binding Items}">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="Background" Value="Blue" />
<Setter Property="BorderBrush" Value="Blue" />
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem}, Path=IsSelected}" Value="True">
<DataTrigger.Setters>
<Setter Property="Foreground" Value="White"></Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumnHeader Content="Text"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding MyImage}" Width="20"/>
<Label Content="{Binding MyLabelText}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

How to change color for specific value in Listview

I want to change color according to value: Pass(Blue) and Fail(Red). I want to change only text color of state's value.
main.xaml
<ListView x:Name="record_List"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="203" Width="382" Margin="553,454,0,0"
BorderThickness="0">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn Header="State" Width="52"
DisplayMemberBinding="{Binding state}"/>
<GridViewColumn Header="Stuednt num" Width="80"
DisplayMemberBinding="{Binding snum}"/>
<GridViewColumn Header="Name" Width="75"
DisplayMemberBinding="{Binding name}"/>
<GridViewColumn Header="Check time"
DisplayMemberBinding="{Binding check_time}"/>
</GridView>
</ListView.View>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewMouseLeftButtonDown"
Handler="ListViewItem_PreviewMouseLeftButtonDown"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Use style triggers for column State, you try:
Fixed:
<GridViewColumn Header="State" Width="52" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding state}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Black"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding state}" Value="Pass">
<Setter Property="Foreground" Value="Blue"/>
</DataTrigger>
<DataTrigger Binding="{Binding state}" Value="Fail">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The easiest way would be to use style and DataTriggers:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Gray"/>
<Style.Triggers>
<DataTrigger Binding="{Binding testResult}" Value="Pass">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding testResult}" Value="Fail">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>

How do I access an outer collection itemsource property from an inner collection?

I have two collections.
The 'OuterCollection' collection contains the 'InnerCollection' collection and a property called 'OuterProperty'. In my 'InnerCollection', it only contains one property called 'InnerProperty'.
Now my ViewModel contains 1 'OuterCollection'. And it's set to the data context of the control. So a very easy set up.
ViewModel
{
OuterCollection;
}
OuterCollection
{
InnerCollection;
OuterProperty;
}
InnerCollection
{
InnerProperty;
}
Now in the code, I want to be able to access my 'OuterProperty' from a trigger within the context of my 'InnerCollection' How can I do this? And if I can't do this, is there an alternative way to accomplish this?
Here's my attempt:
<ListView ItemsSource="{Binding Path=OuterCollection}" />
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding Path=InnerCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image>
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=InnerProperty}" Value="blah" />
<Condition Binding="{Binding Path=DataContext.OuterCollection.OuterProperty, RelativeSource ={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Converter={StaticResource IsStringNullOrEmpty}}" Value="true" />
</MultiDataTrigger.Conditions>
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock Text="test"/>
</Setter.Value>
</Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

changing binding based on datatrigger property

I'm trying to change the text of a textblock based on a datatrigger. The datatrigger looks like this:
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShowFileExtensionsProperty}" Value="true">
<Setter Property="Text" Value="{Binding Path=Name}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ShowFileExtensionsProperty}" Value="false">
<Setter Property="Text" Value="{Binding Path=NameWithoutExtension}" />
</DataTrigger>
</Style.Triggers>
</Style>
This code is found within the xaml file of the class "MyView" The cs file of this class contains the following code:
public static readonly DependencyProperty ShowFileExtensionsProperty =
DependencyProperty.Register("ShowFileExtensions", typeof(bool), typeof(MyView), new UIPropertyMetadata(false));
public bool ShowFileExtensions
{
get { return (bool)GetValue(ShowFileExtensionsProperty); }
set
{
SetValue(ShowFileExtensionsProperty, value);
updateViewCollection();
}
}
The textblock is displayed within a listview, that has been bound to a list of objects, these objects contain the property "Name" and "NameWithoutExtension".
The problem is that the text in the textblock always stays blank. Somehow the datatrigger is never triggered. Any idea what is wrong with the datatriggers?
PS: The full code follows
<UserControl x:Class="com.xploreplus.Filedrops.explorer.listview.FiledropsFileList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:l="clr-namespace:com.xploreplus.Filedrops.explorer.listview.views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="Extension" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShowFileExtensionsProperty, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="true">
<Setter Property="Text" Value="brol2" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=ShowFileExtensionsProperty, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="false">
<Setter Property="Text" Value="blabla" />
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<ListView Name="viewComponent">
<ListView.View>
<GridView>
<GridViewColumn Header="">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Source="{Binding Path=Icon}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource Extension}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Extension" DisplayMemberBinding="{Binding Path=Extension}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
As the textblocks are shown in listview then the DataContext of textblock will the ItemDataContext if not set explicitly. That is why your bindings are not working. You will have to provide the relativesource to binding
Try updating the bindings like
<DataTrigger Binding="{Binding Path=ShowFileExtensions, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="true">
used {x:Type Control} assuming this is the type of your view else you will have to change to your view type.
Hope this helps
Thanks

Categories