当前位置: 首页 > 知识库问答 >
问题:

在MVVM中选择TreeViewItem

段宏毅
2023-03-14

我想使树状视图与可编辑的节点。我在谷歌上搜索了这篇好文章:

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

但是我有一个问题。我的TreeView形成了dinamally,而不是静态的角质层。就像那样

    <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>

DocPackageExtendedList的列表。

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

第二个问题——在我得到实例TreeViewItem后,我如何从TreeView项的数据模板中获得EditableTextBlock。

添加答案

我已经试过了。因为在MVVM视图模型中不能有任何链接来查看像TreeView这样的对象,我在代码隐藏中创建了处理程序,就像这样

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个答案

屈星腾
2023-03-14

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

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

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

第二个问题:通过var container=yourTreeInstance获取数据项的容器。ItemContainerGenerator。ContainerFromItem(dataInstance) 。现在,您必须在VisualTreeHelper的帮助下遍历此容器,直到它找到类型为EditableTextBlock的控件。但我不会在ViewModel中这样做,而是在助手类中或在附加属性的帮助下这样做。

EDIT:您正在将DocPackage扩展类的Childs属性中的实例的IsEdable属性绑定到EditableTextBox,但是在您的Test命令方法中,您正在直接操作DocPackage扩展实例的IsEdable属性。您可以执行以下操作:

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;
    }
}

晏卓君
2023-03-14

这可能对你有帮助。

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;
    }
 类似资料:
  • 我在后台有< code>ViewModel(实现< code > INotifyPropertyChanged )和类< code>Category,它只有一个< code>string类型的属性。我的ComboBox SelectedItem绑定到类别的实例。当我更改instance的值时,SelectedItem没有更新,Combobox也没有更改。 编辑:代码 组合框: 物业: 我尝试的是:

  • 我有一个列表类型的组合框。我通过datacontext绑定了ItemsSource和ItemSelected。如果所选项目已经更改,我会显示一条弹出消息,确认用户的操作。单击“确定”后,选择会发生变化。但是在点击“取消”时,选择应该被取消,而先前的项目应该被保留。下面是绑定到combobox的SelectedItem的属性。 组合框在弹出窗口中。那么Dispatcher对象在这种情况下能工作吗?

  • 我有两个dropdownlist,它使用MVVM初始化。从一个瀑布到另一个瀑布。 虽然一切正常,但我发现当我编辑表单,并选择dropDownlist到选项标签(清除其值,这是有效的,因为它不是必需的字段),该值是不清楚的。因此,在我点击保存按钮后,旧值被保存。 dropdownlist都有这样的行为。(选择选项标签未重置/清除后面绑定的模型的值) 当我选择选项标签时,如何绑定空或空值,或重置值?

  • 问题内容: 我是MSSQL用户,现在将数据库转换为MySQL。我在MySQL中编写以下查询: 我得到以下错误 如何用MySQL正确编写这样的查询? 问题答案: 使用CREATE TABLE SELECT语法。 http://dev.mysql.com/doc/refman/5.0/en/create-table- select.html

  • 问题内容: 目前,我正在使用此: 它将我重定向到选项值内的位置。但这不能按预期工作。..这意味着如果我单击select的第一个选项,则onChange操作不会运行。我正在考虑使用javascript,但我想您会收到一些更好的建议。因此,如果我单击每个选项将其重定向到它的值,该如何使其起作用? 问题答案: 因为已经选择了第一个选项,所以永远不会触发change事件。添加一个空值作为第一个值,并检查位

  • 问题内容: 我的网站范围相当广泛,最近我刚切换到PHP5(称我为后期开发者)。 我之前所有的MySQL查询都是这样构建的: 这使得它非常容易,简单和友好。 由于明显的安全性原因,我现在正尝试切换到mysqli,并且在需要特定参数时很难弄清楚如何实现相同的查询。 这句话已成为过去吗? 如果是的话,如何处理涉及大量列的查询?我真的需要每次都把它们全部打出来吗? 问题答案: 变成 传递给: OP评论: