在MVVM中获取选定的TreeViewItem

时间:2013-09-23 06:31:57

标签: wpf mvvm datatemplate treeviewitem

我希望使用可编辑节点制作TreeView。正如我想的那样,我用谷歌搜索了这篇文章:

http://www.codeproject.com/Articles/31592/Editable-TextBlock-in-WPF-for-In-place-Editing

但我有问题。我的TreeView形成了dinamically,而不是像arcticle那样静态。像那样

    <TreeView Name="_packageTreeView" Margin="5" ItemsSource="{Binding PackageExtendedList}">
         <TreeView.InputBindings>
             <KeyBinding Key="C" Command="{Binding *TestCommand*}" CommandParameter="{Binding}" />
         </TreeView.InputBindings>
         <i:Interaction.Triggers>
             <i:EventTrigger EventName="SelectedItemChanged">
                 <i:InvokeCommandAction Command="{Binding PackageTreeItemChangeCommand}" CommandParameter="{Binding ElementName=_packageTreeView, Path=SelectedItem}"/>
             </i:EventTrigger>
         </i:Interaction.Triggers>
         <TreeView.ItemContainerStyle>
             <Style TargetType="{x:Type TreeViewItem}">
                 <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
             </Style>
         </TreeView.ItemContainerStyle>
         <TreeView.ItemTemplate>
             <HierarchicalDataTemplate DataType="{x:Type MasterBuisnessLogic:RootDocPackage}" ItemsSource="{Binding Path=Childs}">
                 <Grid>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition>
                         </ColumnDefinition>
                         <ColumnDefinition>
                         </ColumnDefinition>
                     </Grid.ColumnDefinitions>
                    <Image Source="/Resources/DocGroup.png"></Image>
                    <Etb:EditableTextBlock Margin="5,0,0,0" Grid.Column="1" Text="{Binding Path=Name}"></Etb:EditableTextBlock>
                 </Grid> 
             </HierarchicalDataTemplate>
         </TreeView.ItemTemplate>
     </TreeView>

PackageExtendedList - DocPackageExtended列表。

所以,第一个问题 - 如何在TestCommand中获取TreeViewItem实例?不是实例 DocPackageExtended 类!我想在文章中选择 TreeViewItem 实例。

第二个问题 - 在我获得实例 TreeViewItem 之后,如何从TreeView项目的DataTemplate中获取 EditableTextBlock

添加了答案

我已经尝试过了。 MVVM中的原因ViewModel不能像TreeView一样有View对象的链接,我在代码隐藏中设置处理程序,就像那样

private void TreeViewItemSelected(object sender, RoutedEventArgs e)
{
    // Already have TreeViewItem instance without of ItemContainerGenerator help
    var tvi = e.OriginalSource as TreeViewItem;

    if (tvi == null)
        return;

    var etb = VisualTreeLib.VisualTreeLib.GetVisualChild<EditableTextBlock>(tvi);
    if (etb == null)
        return;

    // Do what I want
    etb.IsEditable = true;
}

不幸的是,这没有任何影响:(

我也试过这种方法,但也失败了。

DocPackageExtended类型中的

我定义了属性

public bool IsEditable
{
    get { return _isEditable; }
    set
    {
        _isEditable = value;
        OnPropertyChanged(new PropertyChangedEventArgs("IsEditable"));
    }
}

而不是XAML中的变化:

<Etb:EditableTextBlock Margin="5,0,0,0" Grid.Column="1" Text="{Binding Path=Name}" *IsEditable="{Binding Path=IsEditable}"*/>

并在ViewModel中

private void TestCommandMethod(object obj)
{
    var dpe = obj as DocPackageExtended;
    if (dpe == null)
       return;
    dpe.IsEditable = true;
}

也不起作用:( 有什么想法吗?

2 个答案:

答案 0 :(得分:0)

第一个问题:由于您似乎可以选择多个条目,因此需要在TestCommand执行的方法中过滤所有选定的条目:

IEnumerable<DocPackageExtended> selectedEntries = PackageExtendedList.Where(d => d.IsSelected);

如果禁用了多个选择,您可以将TreeView的选定项绑定到VM中的属性,并在TestCommand的方法中访问此属性。

第二个问题:您通过var container = YourTreeViewInstance.ItemContainerGenerator.ContainerFromItem(dataInstance);获取了dataitem的容器。现在,您必须在VisualTreeHelper的帮助下浏览此容器,直到找到类型EditableTextBlock的控件。但我不会在ViewModel中这样做,而是在辅助类中或在附加属性的帮助下。

编辑:您正在将Childs类的DocPackageExtended属性中的实例的IsEditable属性绑定到EditableTextBox,但在TestCommandMethod中,您正在操纵IsEditable 1}} DocPackageExtended实例的属性直接。您可以执行以下操作:

private void TestCommandMethod(object obj)
{
    var dpe = obj as DocPackageExtended;
    if (dpe == null)
       return;
    dpe.IsEditable = true;
    foreach (RootDocPackage rdp in dpe.Childs)
    {
        rdp.IsEditable = true;
    }
}

答案 1 :(得分:0)

这可能会对你有帮助。

private void Button_Click(object sender, RoutedEventArgs e)
    {
        TreeViewItem treeViewItemFound = GetItem(MyTreeview, MyTreeview.SelectedItem);
        ContentPresenter header = treeViewItemFound.Template.FindName("PART_Header", treeViewItemFound) as ContentPresenter;
        if (header != null)
        {
            TextBox myTextBox = (TextBox)header.ContentTemplate.FindName("MyTextBox", header);
        }
    }

    public TreeViewItem GetItem(ItemsControl container, object itemToSelect)
    {
        foreach (object item in container.Items)
        {
            if (item == itemToSelect)
            {
                return (TreeViewItem)container.ItemContainerGenerator.ContainerFromItem(item);
            }
            else
            {
                ItemsControl itemContainer = (ItemsControl)container.ItemContainerGenerator.ContainerFromItem(item);
                if (itemContainer.Items.Count > 0)
                {
                    TreeViewItem treeViewItemFound = GetItem(itemContainer, itemToSelect);
                    if (treeViewItemFound != null)
                        return treeViewItemFound;
                }
            }
        }

        return null;
    }