简体   繁体   English

当TreeViewItem选择更改时,WPF MVVM更新文本编辑器

[英]WPF MVVM Update text editor when TreeViewItem selection changes

I have a TreeView of DirectoryItems that are defined like this: 我有一个DirectoryItems的TreeView定义如下:

public class DirectoryItem : INotifyPropertyChanged
{
    public String DisplayName { get; set; }
    public String Fullpath { get; set; }
    public ObservableCollection<DirectoryItem> Children { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
}

When the user selects a DirectoryItem from the treeView, I want to take the Fullpath from that item, read all the text from the file, and load it into a text editor. 当用户从treeView中选择DirectoryItem时,我要从该项目中获取Fullpath,从文件中读取所有文本,然后将其加载到文本编辑器中。

My ViewModel has a DisplayText property that the text editor is bound to: 我的ViewModel有一个DisplayText属性,文本编辑器绑定到该属性:

internal class MainWindowViewModel : IMainWindowViewModel
{
    private ObservableCollection<DirectoryItem> DirectoryItems { get; set; }

    public string DisplayText { get; set; }
    //this needs to be implemented to take a filepath and read from it
}

I think there should be a command called that is associated to the TreeViewItem's IsSelected property that passes the Fullpath to the ViewModel, but I haven't been able to get the code working. 我认为应该有一个与TreeViewItem的IsSelected属性相关联的命令,该属性将Fullpath传递给ViewModel,但是我无法使代码正常工作。 How would I implement this? 我将如何实施呢?

Here's what I have that I can't get working, I get a "Property triggers is not attachable to elements of type Style" error: 这是我无法工作的结果,出现“属性触发器无法附加到Style类型的元素”错误:

<Style TargetType="{x:Type TreeViewItem}">
    <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectedItemChanged">
                    <i:InvokeCommandAction Command="{Binding DisplayText}" CommandParameter="{Binding ElementName=treeView, Path=SelectedItem}"/>
                </i:EventTrigger>
    </i:Interaction.Triggers>
</Style>

Thank you. 谢谢。

You can't add an interaction trigger inside a Style . 您不能在Style添加交互触发器。

What you could do is to add an IsSelected property to your DirectoryItem class and bind the IsSelected property of the TreeViewItem to this one: 您可以做的是将一个IsSelected属性添加到DirectoryItem类,并将TreeViewItemIsSelected属性绑定到此对象:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>

public class DirectoryItem : INotifyPropertyChanged
{
    public String DisplayName { get; set; }
    public String Fullpath { get; set; }
    public ObservableCollection<DirectoryItem> Children { get; set; }

    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set { _isSelected = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Make sure that you actually raise the PropertyChanged property whenever the IsSelected is set to a new value. 确保将IsSelected设置为新值时实际上提高了PropertyChanged属性。

The view model could then hook up to the PropertyChanged event of each item in the ObservableCollection<DirectoryItem> and do something whenever an item is selected: 然后,视图模型可以连接到ObservableCollection<DirectoryItem>中每个项目的PropertyChanged事件,并在选择某个项目时执行以下操作:

internal class MainWindowViewModel : IMainWindowViewModel
{
    public MainWindowViewModel()
    {
        //add the items...
        DirectoryItems.Add(new DirectoryItem() { DisplayName = "test", Children = new ObservableCollection<DirectoryItem>() { new DirectoryItem() { DisplayName = "child" } } });

        foreach(var item in DirectoryItems)
        {
            item.PropertyChanged += Item_PropertyChanged;
        }
    }

    private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == "IsSelected")
        {
            DirectoryItem selectedItem = sender as DirectoryItem;
            //set the DisplayText property
        }
    }

    public ObservableCollection<DirectoryItem> DirectoryItems { get; set; } = new ObservableCollection<DirectoryItem>();

    public string DisplayText { get; set; }
}

If you are adding items dynamically to the ObservableCollection<DirectoryItem> you probably also want to handle the CollectionChanged event to hook up event handlers to any new objects as well: 如果要将项目动态添加到ObservableCollection<DirectoryItem> ,则可能还需要处理CollectionChanged事件,以将事件处理程序也连接到任何新对象:

private void DirectoryItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems != null)
    {
        foreach (object item in e.NewItems)
        {
            (item as INotifyPropertyChanged).PropertyChanged
                += new PropertyChangedEventHandler(Item_PropertyChanged);
        }
    }

    if (e.OldItems != null)
    {
        foreach (object item in e.OldItems)
        {
            (item as INotifyPropertyChanged).PropertyChanged
                -= new PropertyChangedEventHandler(Item_PropertyChanged);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM