2017-06-13 26 views
2

我有IsSelected屬性的問題。它不會將值從視圖發送到視圖模型。我貼我的代碼如下 視圖模型:TreeViewItem在Xaml中選擇MVVM不會將值發送到View-Model

public class Viewmodel : INotifyPropertyChanged 
{ 
    private ObservableCollection<int> seznam; 
    public ObservableCollection<int> Seznam 
    { 
     get { return seznam; } 
     set 
     { 
      seznam = value; 
     } 
    } 

    public Viewmodel() 
    { 
     Seznam = new ObservableCollection<int>(); 
     for (int i = 0; i < 3; i++) 
     { 
      Seznam.Add(i); 
     } 
    } 

    bool isSelected; 
    public bool IsSelected 
    { 
     get { return isSelected; } 
     set 
     { 
      isSelected = value; 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

查看:

 <TreeView ItemsSource="{Binding Seznam}"> 
     <TreeView.ItemContainerStyle> 
      <Style TargetType="{x:Type TreeViewItem}"> 
       <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/> 
      </Style> 
     </TreeView.ItemContainerStyle> 
    </TreeView> 

它仍然沒有斷點處,我把對GET停止{返回isSelected; }

+1

任何約束力的錯誤,而你調試? – Chrille

+1

您的視圖模型是否實現INotifyPropertyChnaged?請顯示您的viewmodel的簽名 –

+0

沒有綁定錯誤。 –

回答

0

隨着更新後的文章,很明顯,你還沒有正確實施你的視圖模型。特別是,您的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價值,以及爲IsSelectedIsExpanded狀態屬性的正確方法(因爲你最初曾提到希望兩者) 。

以下是我之前編寫的例子,只是爲了向自己證明通常的方法可以按預期工作。你不應該有任何麻煩適應它,以滿足您的需求&hellip;

每個項目的視圖模型:

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)); 
    } 
} 
+0

您的答案的第一段和第二段解決了我的問題。 –

-1

而不是在樹中的每個節點上使用IsSelected,使用TreeView本身上的TreeView.SelectedItem。從這裏你可以綁定,但該屬性是隻讀的。

相關問題