Avec votre message mis à jour, il est clair que vous n'avez pas implémenté correctement vos modèles de vue. En particulier, votre TreeView.ItemsSource
est lié à la propriété Seznam
de votre seul modèle de vue. Ceci est une collection de valeurs int
.
Cela signifie que le contexte de données pour chaque conteneur d'éléments dans le TreeView
, où vous tentez de vous lier à la propriété IsSelected
, est une valeur int
. Et bien sûr, les valeurs int
n'ont même pas de propriété IsSelected
.
(Soit dit en passant, je suis sceptique sur your claim that "There are no binding errors". Si vous avez regardé la sortie de débogage, vous devriez certainement avoir vu une erreur de liaison, où la tentative de lier à l'inexistante IsSelected
propriété.)
Et Pensez-y un instant: en supposant que le conteneur d'éléments ait réussi à se lier à la propriété Viewmodel.IsSelected
. Combien de conteneurs d'articles pensez-vous qu'il y a? Et combien d'instances de Viewmodel
penses-tu qu'il y a? Vous devez croire qu'il existe de nombreux conteneurs d'éléments, à savoir un pour chaque élément de votre collection. Et qu'il n'y a qu'une instance de Viewmodel
. Alors, comment l'état de sélection de tous ces éléments pourrait-il correspondre à la propriété unique Viewmodel.IsSelected
?
La bonne façon de le faire serait de créer un objet modèle de vue distinct pour la collecte, avec une propriété pour votre valeur int
, ainsi que des propriétés pour les IsSelected
et IsExpanded
états (puisque vous aviez initialement mentionné vouloir les deux) .
Voici l'exemple que j'ai écrit plus tôt juste pour me prouver que l'approche habituelle fonctionnerait comme prévu.Vous ne devriez pas avoir de difficulté à l'adapter à vos besoins & hellip;
modèle de vue par élément:
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})"; }
}
}
modèle Vue principale pour la fenêtre:
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 pour la fenêtre:
<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>
Et pour l'exhaustivité & hellip;
La classe de base pour boilerplate INotifyPropertyChanged
mise en œuvre:
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));
}
}
Toute erreur de liaison pendant que vous Debug? – Chrille
Votre modèle de vue implémente-t-il INotifyPropertyChnaged? S'il vous plaît montrer la signature de votre viewmodel –
Il n'y a pas d'erreur de liaison. –