Я создал тему «DarkMode» для своего приложения, но привязка IsSelected
для ListViewItem
не работает. Когда я выбираю элемент / элементы, они выделяются, как и ожидалось (т.е. MultiTriggers применяют правильный цвет выделения), поэтому ListView явно думает IsSelected == True
. Но Setter никогда не вызывается, поэтому свойство в моей модели никогда не обновляется.
Если я удаляю стиль x:Key="RemoteComputerItem"
, он работает нормально (т.е. вызывается Setter и моя модель обновляется). Удаление всех триггеров в этом стиле не имеет значения (очевидно, я не вижу выделенных элементов, но Setter по-прежнему не вызывается). Таким образом, остается только следующее:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd">
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
</Border>
</ControlTemplate>
Я считаю, что проблема заключается в приведенном выше шаблоне элемента управления, но я не могу понять, как это исправить. Я что-то пропустил? или мне нужно использовать что-то еще вместо GridViewRowPresenter
?
Мой XAML ниже. Я не включил C#, так как думаю, что проблема здесь и не хочу, чтобы вопрос был слишком длинным, но я рад добавить его, если необходимо.
Просмотр:
<ListView x:Name="ADComputers" Margin="0" Padding="0" Grid.Row="1" Grid.Column="2"
ItemsSource="{Binding SelectedItem.Computers, ElementName=ADTree, Mode=TwoWay}"
SelectionMode="Multiple" ItemContainerStyle="{DynamicResource RemoteComputerItem}">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource RemoteComputerItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Style.Triggers>
<DataTrigger Binding="{Binding StatusText}" Value="Offline">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="" Width="20">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="Name" Width="120" DisplayMemberBinding="{Binding Name}">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Computer Name" util:SortOrderGlyph.IsSorted="False" util:SortOrderGlyph.SortDirection="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="SortCol">
<cal:Parameter Value="Name" />
<cal:Parameter Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewColumnHeader}}}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<!-- More columns like above, removed to shorten -->
</GridView>
</ListView.View>
</ListView>
Отдельный словарь ресурсов для темы DarkMode:
<Style x:Key="RemoteComputerItem" TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd">
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource ControlMouseOverColor}" />
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource SelectedBackgroundColor}" />
</Setter.Value>
</Setter>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource SelectedBackgroundColor}" />
</Setter.Value>
</Setter>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
РЕДАКТИРОВАТЬ:
Здесь еще немного кода, чтобы дать вам полную картину привязок, но, как я упоминал выше, привязки отлично работают, когда я удаляю шаблон элемента управления для ListViewItem.
Как вы можете видеть выше, ListView привязан к SelectedItem.Computers
элемента ADTree
. Вот XAML для ADTree
:
<TreeView Margin="0, -1, 0, 0" Grid.Row="1" Grid.Column="0" x:Name="ADTree" ItemsSource="{Binding ADRoot.Children}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:OUModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
TreeView привязан к ADRoot.Children
:
class ADTreeViewModel : OUModel
{
public OUModel ADRoot { get; set; } = new OUModel(null, false);
}
class OUModel : PropertyChangedBase, ITreeViewItemViewModel
{
// TreeView is bound to this property, which holds a collection of more OUModel objects
public BindableCollection<ITreeViewItemViewModel> Children { get; set; } = new BindableCollection<ITreeViewItemViewModel>();
// The ListView's ItemSource is bound to ADTree.SelectedItem.Computers which is this property
public List<RemoteComputer> Computers
{
get { return computers; }
set { computers = value; NotifyOfPropertyChange(); }
}
// PropertyChangedBase is from Caliburn.Micro
class RemoteComputer : PropertyChangedBase
{
// All other properties in this class are being displayed correctly in the ListView, so the DataContext is correct E.g.:
public string Name { get; set; }
private bool isSelected = false;
// The ListViewItem's IsSelected property is bound to this
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
NotifyOfPropertyChange(); // Caliburn.Micro gets the property name itself
// I've also tried adding the following
NotifyOfPropertyChange(() => Parent.Children);
NotifyOfPropertyChange(() => Parent);
}
}
}
Вот проводник Live Property для выбранного элемента: