隨着更新後的文章,很明顯,你還沒有正確實施你的視圖模型。特別是,您的TreeView.ItemsSource
綁定到您的唯一視圖模型的Seznam
屬性。這是一個int
值的集合。
這意味着TreeView
中您嘗試綁定到IsSelected
屬性的每個項目容器的數據上下文是int
值。當然,int
值甚至沒有IsSelected
屬性。
(順便說一句,我很懷疑your claim that "There are no binding errors"。如果你看了調試輸出,你當然應該已經看到了綁定錯誤,在試圖綁定到不存在的IsSelected
屬性。)
而且想一想:假設物品容器設法綁定到Viewmodel.IsSelected
屬性。你認爲有多少個物品容器?你認爲有多少個Viewmodel
實例?你應該認爲有很多物品容器,即爲您的集合中的每個物品一個。並且只有一個Viewmodel
的實例。那麼,所有這些物品的選擇狀態如何映射到單個Viewmodel.IsSelected
屬性呢?
要做到這一點是創建爲集合的單獨視圖模型對象,以財產爲您int
價值,以及爲IsSelected
和IsExpanded
狀態屬性的正確方法(因爲你最初曾提到希望兩者) 。
以下是我之前編寫的例子,只是爲了向自己證明通常的方法可以按預期工作。你不應該有任何麻煩適應它,以滿足您的需求…
每個項目的視圖模型:窗
class TreeItemViewModel : NotifyPropertyChangedBase
{
public ObservableCollection<TreeItemViewModel> Items { get; }
= new ObservableCollection<TreeItemViewModel>();
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set { _UpdateField(ref _isSelected, value, _OnBoolPropertyChanged); }
}
private bool _isExpanded;
public bool IsExpanded
{
get { return _isExpanded; }
set { _UpdateField(ref _isExpanded, value, _OnBoolPropertyChanged); }
}
private void _OnBoolPropertyChanged(bool obj)
{
_RaisePropertyChanged(nameof(FullText));
}
private string _text;
public string Text
{
get { return _text; }
set { _UpdateField(ref _text, value, _OnTextChanged); }
}
private void _OnTextChanged(string obj)
{
_RaisePropertyChanged(nameof(FullText));
}
public string FullText
{
get { return $"{Text} (IsSelected: {IsSelected}, IsExpanded: {IsExpanded})"; }
}
}
主視圖模型:
class MainViewModel : NotifyPropertyChangedBase
{
public ObservableCollection<TreeItemViewModel> Items { get; }
= new ObservableCollection<TreeItemViewModel>();
public ICommand ClearSelection { get; }
public MainViewModel()
{
ClearSelection = new ClearSelectionCommand(this);
}
class ClearSelectionCommand : ICommand
{
private readonly MainViewModel _parent;
public ClearSelectionCommand(MainViewModel parent)
{
_parent = parent;
}
#pragma warning disable 67
public event EventHandler CanExecuteChanged;
#pragma warning restore 67
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_parent._ClearSelection();
}
}
private void _ClearSelection()
{
_ClearSelection(Items);
}
private static void _ClearSelection(IEnumerable<TreeItemViewModel> collection)
{
foreach (TreeItemViewModel item in collection)
{
_ClearSelection(item.Items);
item.IsSelected = false;
item.IsExpanded = false;
}
}
}
XAML的窗口:
<Window x:Class="TestSO44513864TreeViewIsSelected.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:l="clr-namespace:TestSO44513864TreeViewIsSelected"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:MainViewModel>
<l:MainViewModel.Items>
<l:TreeItemViewModel Text="One">
<l:TreeItemViewModel.Items>
<l:TreeItemViewModel Text="One A"/>
<l:TreeItemViewModel Text="One B"/>
</l:TreeItemViewModel.Items>
</l:TreeItemViewModel>
<l:TreeItemViewModel Text="Two"/>
<l:TreeItemViewModel Text="Three"/>
</l:MainViewModel.Items>
</l:MainViewModel>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Clear Selection" Command="{Binding ClearSelection}"
HorizontalAlignment="Left"/>
<TreeView ItemsSource="{Binding Items}" Grid.Row="1">
<TreeView.ItemContainerStyle>
<p:Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
</p:Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="l:TreeItemViewModel"
ItemsSource="{Binding Items}">
<TextBlock Text="{Binding FullText}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
爲了完整性&hellip;
爲INotifyPropertyChanged
實現樣板的基類:
class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void _UpdateField<T>(ref T field, T newValue,
Action<T> onChangedCallback = null,
[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, newValue))
{
return;
}
T oldValue = field;
field = newValue;
onChangedCallback?.Invoke(oldValue);
_RaisePropertyChanged(propertyName);
}
protected void _RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
任何約束力的錯誤,而你調試? – Chrille
您的視圖模型是否實現INotifyPropertyChnaged?請顯示您的viewmodel的簽名 –
沒有綁定錯誤。 –