WPF TreeView HierarchicalDataTemplate получить TreeViewItem - PullRequest
3 голосов
/ 04 июля 2010

Я использую HierarchicalDataTemplate, чтобы связать мои классы с TreeView с флажками.У меня код работает нормально, и все отображается нормально, но я хотел бы иметь возможность получить список дочерних элементов в моем дереве.

Когда флажок установлен, я хочу иметь возможностьвыбрать родительские узлы и дочерние узлы.Если бы у меня был доступ к TreeViewItem, который должен был обернуть флажок, я мог бы легко сделать это, но свойство Parent флажка пусто ... Я могу только получить доступ к своим классам, которые отображаются в HierarchicalDataTemplate.

<TreeView Margin="12" Name="trv1" SelectedItemChanged="trv1_SelectedItemChanged">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type src:Location}" ItemsSource="{Binding Path=Sublocations}">
                <CheckBox Content="{Binding Name}" Tag="{Binding}" IsChecked="{Binding IsChecked}" Click="checkBox_Click"/>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type src:Sublocation}" ItemsSource="{Binding Path=Children}">
                <CheckBox Content="{Binding Name}" Tag="{Binding}" IsChecked="{Binding IsChecked}" Click="checkBox_Click"/>
            </HierarchicalDataTemplate>

            <DataTemplate DataType="{x:Type src:Child}">
                <CheckBox Content="{Binding Name}" Tag="{Binding}" IsChecked="{Binding IsChecked}" Click="checkBox_Click"/>
            </DataTemplate>

        </TreeView.Resources>
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsSelected" Value="{Binding IsChecked}"/>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

Ответы [ 4 ]

1 голос
/ 02 апреля 2013

Вам необходимо добавить узел Children и Parent в ваши классы TreeViewItem.Вам нужно установить Parent / Children при инициализации.

<HierarchicalDataTemplate x:Key="TreeViewItem" ItemsSource="{Binding Children}">
    <CheckBox Margin="2" IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Name}" />
</HierarchicalDataTemplate>
<TreeView ItemsSource="{Binding Countries}" ItemTemplate="{StaticResource TreeViewItem}" />

В ваших viewModels.

public class MainPageViewModel
{
    public ObservableCollection<Country> Countries {get;set;}
}

public class Country
{
    public string Name {get; set;}
    public bool IsChecked {get;set;}
    public IEnumerable<State> Children {get; set;}
    // Do not need parent for this.
}

public class State
{
    public string Name {get; set;}
    public bool IsChecked {get; set;}
    public Country Parent {get; set;}
    public IEnumerable<City> Children {get; set;}
}

public class City
{
    public string Name {get; set;}
    public bool IsChecked {get; set;} 
    public State Parent {get; set;}
}
0 голосов
/ 15 ноября 2010

К вашему сведению: вместо того, чтобы получить TreeViewItem, я считаю, что лучше включить ссылку на родителя в вашу модель, так же как в вашем классе узлов:

Node.Parent {get{return this._parent;}}

Тогда при создании вашей коллекции вы должны были бы установить значения, но это невероятно облегчает жизнь: представьте себе, что вы родитель для любой ступени:

myNode.Parent.Parent.Parent

Чтобы получить TreeViewItem: (из моего ответа здесь: Как получить TreeViewItem из элемента HierarchicalDataTemplate? )

Мне пришлось установить последний выбранный TreeViewItem в перенаправленном событии TreeViewItem.Selected, которое всплывает до представления дерева (сами TreeViewItem не существуют во время разработки, поскольку мы используем HierarchicalDataTemplate).

Событие может быть записано в XAML следующим образом:

Тогда последний выбранный TreeViewItem может быть установлен в событии следующим образом:

private void TreeViewItemSelected(object sender, RoutedEventArgs e)
{
    TreeViewItem tvi = e.OriginalSource as TreeViewItem;

    // set the last tree view item selected variable which may be used elsewhere as there is no other way I have found to obtain the TreeViewItem container (may be null)
    this.lastSelectedTreeViewItem = tvi;

    ...
 }
0 голосов
/ 26 января 2011

Если вы хотите придерживаться шаблона MVVM , вы должны сделать следующее: вызвать команду при изменении выбора (я говорю о событии TreeView.SelectedItemChanged).* Затем используйте эту команду для обновления свойства SelectedItems в модели представления.

public class MyViewModel
{
    // your view model code...
    // ........................

    // this object better be more strongly typed
    private object _mySelectedItem; 

    public object MySelectedItem
    {
        get { return _mySelectedItem; }
        set { 
              _mySelectedItem = value;

              // the following method will handle the changed item. Problem solved              
              HandleTheNewChangedItem(value);
            }
    }
}
0 голосов
/ 05 июля 2010

Я придумала решение, которое может быть не оптимальным, но оно работает. Я добавил EventSetter в стиле TreeView и назначил событие click для объектов TreeViewItem.

            <TreeView.ItemContainerStyle>
                <Style TargetType="TreeViewItem">
                    <Setter Property="IsSelected" Value="{Binding IsChecked}"/>
                    <EventSetter Event="Selected" Handler="tvi_Selected"/>
                </Style>
            </TreeView.ItemContainerStyle>

Таким образом, я могу получить доступ к объекту отправителя, который является TreeViewItem, и перемещаться по узлам.

EDIT: Это «решение» дает мне только верхний объект TreeViewItem, а не выбранный, который является дочерним по отношению к объекту.

РЕДАКТИРОВАТЬ 2: Кажется, древовидные элементы не позволяют мне получить доступ к дочерним древовидным элементам или родительским древовидным элементам. Наверное, я ошибался.

...