获取 ToolBar Button 以触发所选 TreeView 项的方法

Get ToolBar Button to trigger a method for the selected TreeView item

我正在编写一个 MVVM 应用程序(使用 Caliburn.Micro),它加载 Active Directory 树、显示所选 OU 的计算机并在这些计算机上运行 WMI 查询。我想创建一个工具栏按钮,它基本上刷新计算机的数据(即重新运行 WMI 查询)。我正在努力弄清楚如何让我的工具栏按钮为所选项目 (OUModel) 触发 QueryRemoteComputers()。我已经尽可能简化了代码,所以希望这很容易阅读。

TreeView 的视图模型

class TreeViewItemViewModel : ITreeViewItemViewModel
{
    static readonly TreeViewItemViewModel dummyChild = new TreeViewItemViewModel();
    private bool isExpanded;

    public TreeViewItemViewModel Parent { get; set; }
    public BindableCollection<TreeViewItemViewModel> Children { get; set; }
    public bool IsExpanded { 
        get
        { return isExpanded; }
        set
        { // Expand parents, remove dummy child etc }
    }
    public virtual bool IsSelected { get; set; }
    // A few more things like virtual LoadChildren etc
}

查看模型

class ADTreeViewModel : TreeViewItemViewModel
{

    public ADTreeViewModel(LaunchRequest launchRequest) : base(null, false) // Loading the top level OUs now, so setting lazyLoadChildren to false (it will be set to true for the children later)
    {
        LoadChildren();
    }

    protected override void LoadChildren()
    {
        // Fetch top level OUs from AD

        // Add each OU to the TreeView
        foreach (var ou in ous)
        {
            if (ou.Members["ObjectClass"].Value.ToString() == "organizationalUnit")
            {
                base.Children.Add(new OUModel(ou.Members["Name"].Value.ToString(), ou.Members["DistinguishedName"].Value.ToString(), this));
            }
        }

    }

    #region Toolbar Buttons
    public void UpdateComputerStatus() // <<< Bound to toolbar button Click event
    {
        // QueryRemoteComputers(); // How can I call this for the selected tree view item/OUModel
    }
    #endregion // Toolbar Buttons

}

Active Directory OU 模型

class OUModel : TreeViewItemViewModel
{
    private bool isSelected = false;

    #region Bindable Properties
    public string Name { get; set; }
    public string DistinguishedName { get; set; }
    public List<RemoteComputer> Computers { get; set; } = new List<RemoteComputer>();
    public override bool IsSelected
    {
        get { return isSelected; }
        set
        {
            if (isSelected != value)
            {
                isSelected = value;

                if (tokenSource != null) // If any 'QueryRemoteComputers' tasks are still running, cancel them (Happens if the user changes OU before queries are completed)
                {
                    tokenSource.Cancel(); 
                }

                LoadComputers();
                QueryRemoteComputers();
            }
        }
    }
    #endregion // Bindable Properties

    public OUModel(string name, string distinguishedName, TreeViewItemViewModel parent) : base(parent, true)
    {
        Name = name;
        DistinguishedName = distinguishedName;
    }

    private void LoadComputers()
    {
        // Fetch computers in OU
        foreach (var computer in comps)
        {
            Computers.Add(new RemoteComputer(computer.Members["Name"].Value.ToString(), computer.Members["DNSHostName"].Value.ToString(), computer.Members["DistinguishedName"].Value.ToString()));
        }
    }

    private void QueryRemoteComputers() // <<< I want to call this
    {
        foreach (RemoteComputer computer in Computers)
        {
            // Run WMI queries on remote computers and store the results
            computer.Property = etc;
        }
    }
}

TreeView 通过(即 ADTreeViewModel.Children)绑定:

<TreeView Grid.Row="1" Grid.Column="0" x:Name="ADTree" ItemsSource="{Binding Children}">

计算机 ListView 通过以下方式绑定到 TreeView 的 SelectedItem:

<ListView Grid.Row="1" Grid.Column="2" ItemsSource="{Binding SelectedItem.Computers, ElementName=ADTree, Mode=OneWay}">

我已经找到了一种使用 lambda 表达式的方法。

public void UpdateComputerStatus() // <<< Bound to toolbar button Click event
{
    TreeViewItemViewModel selectedItem = Children.Where(c => c.IsSelected == true).FirstOrDefault();
    OUModel ou = selectedItem as OUModel;

    if (ou != null)
    {
        ou.QueryRemoteComputers();
    }  
}