65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ViewModel (MVVM) 以编程方式扩展 Silverlight Tree View 控件节点

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (18投票s)

2010年10月22日

Ms-PL

2分钟阅读

viewsIcon

116090

downloadIcon

2753

使用 ViewModel (MVVM) 以编程方式选择 Silverlight Tree View 控件节点。

Silverlight 树形视图控件和视图模型 (MVVM)

实时示例: http://silverlight.adefwebserver.com/ViewModelTreeControl

另请参阅: Silverlight DataTrigger 是解决视图模型/MVVM 问题的答案

当使用 Silverlight 树形视图控件时,您会发现如果没有使用代码隐藏,则程序化展开树节点并不容易。本文展示了如何使用 行为来实现这一点。

使用 Silverlight 树形视图控件

让我们看一下使用 视图模型 (MVVM) 的 Silverlight 树形视图控件的正常操作

我们从一个简单的 Category(类别)类开始...

Click to enlarge image

我们将 Categories(类别)的集合绑定到 树形视图控件

我们创建一个 ICommand,它将设置其中一个节点的 IsSelected 属性

public ICommand SetCategoryCommand { get; set; }
public void SetCategory(object param)
{  
    foreach (var Cat in colCategory)
    {
        // Find the Node
        var result = (from objCategory in Cat.AllChildren()
                        where objCategory.CategoryName == "Category Sub1-1"
                        select objCategory).FirstOrDefault();
                        
        if (result != null)
        {
            // Set the IsSelected property so the checkbox
            // will be checked
            result.IsSelected = true;
        }
    }
}

private bool CanSetCategory(object param)
{
    return true;
}

然后,我们可以使用 Button(按钮)调用 ICommand,并选中节点上的复选框。

问题是,如果 Silverlight 树形视图控件处于折叠状态,则 Node(节点)将被选中,但除非您展开树 Node(节点),否则您不会知道它。

程序化地选择树节点

程序化地选择 Tree Node(树节点)的第一步是在 View Model(视图模型)中创建一个属性以保存所选节点的值

private Category _SelectedCategory;
public Category SelectedCategory
{
    get { return _SelectedCategory; }
    set
    {
        if (SelectedCategory == value)
        {
            return;
        }
        _SelectedCategory = value;
        this.NotifyPropertyChanged("SelectedCategory");
    }
}

并设置值

// Set the SelectedCategory property
// so the Behavior will know what node to open
SelectedCategory = objCategorySub0;

接下来,我们创建一个 Behavior(行为)并将其放置在 Tree View Control(树形视图控件)上。

我们将 Button(按钮)设置为触发 Behavior(行为),并将 SelectedCategory(选定类别)绑定到 Behavior(行为)

请注意,还有一个 ExpandOnLoad(加载时展开)复选框,允许我们指示节点是在页面加载时展开,还是在触发事件(例如 Button(按钮)点击)时展开。

当我们运行项目并单击 Button(按钮)时...

Silverlight 树形视图控件节点将自动展开。

行为

Behavior(行为)不包含很多代码。 这是完成大部分工作的方法

private void SelectNode()
{
    // Only try to expand Node if the SelectedCategory is set
    if (SelectedCategory != null)
    {
        // Refresh Tree Control
        objTreeView.UpdateLayout();
        // Get the DataContext of the Tree Control
        MainPageViewModel objMainPageViewModel = 
		(MainPageViewModel)objTreeView.DataContext;
        // Get collection of items bound to Tree Control
        ObservableCollection<category> colCategories = 
		(ObservableCollection<category>)objMainPageViewModel.colCategory;
        
        // Loop through the top levels items
        foreach (var Cat in colCategories)
        {
            // Find the Node - Is it a child of this parent?
            var result = (from objCategory in Cat.AllChildren()
                            where objCategory == SelectedCategory
                            select objCategory).FirstOrDefault();
                            
            // If the selected item is a child of the Parent
            if (result != null)
            {
                // Get the Tree Control node container for the item
                TreeViewItem objTreeViewItem = 
		(TreeViewItem)objTreeView.ItemContainerGenerator.ContainerFromItem(Cat);
                // Expand the Node
                objTreeViewItem.IsExpanded = true;
                
                // Refresh Tree Control
                objTreeView.UpdateLayout();
                
                ExpandChildNode(objTreeViewItem, Cat);
            }
        }
    }
}

// This method expands child nodes
private void ExpandChildNode(TreeViewItem objTreeViewItem, Category Cat)
{
    // Loop through all the sub Categories
    foreach (var item in Cat.Categories)
    {
        // Find the Node - Is it a child of this parent?
        var result = (from objCategory in item.AllChildren()
                        where objCategory == SelectedCategory
                        select objCategory).FirstOrDefault();
                        
        // If the selected item is a child of the Parent
        if (result != null)
        {
            // Get the Tree Control node container for the item
            TreeViewItem SubTreeViewItem = (TreeViewItem)
		objTreeViewItem.ItemContainerGenerator.ContainerFromItem(item);
            // Expand the Node
            SubTreeViewItem.IsExpanded = true;
            
            // Refresh Tree Control
            objTreeView.UpdateLayout();
            
            // Recursively call the function                
            ExpandChildNode(SubTreeViewItem, item);
        }
    }
}

代码隐藏有什么问题?

我正在处理一些项目,我们允许 Designer(设计师)(没有编程能力)使用 Microsoft Expression BlendSilverlight 应用程序创建 UI。 因此,我们不想使用任何代码隐藏,因为 Designer(设计师)需要知道如何编程以避免破坏某些东西。

当我们能够实现没有代码隐藏的 Silverlight 项目时,我们不会遇到这个问题。

© . All rights reserved.