从viewModel获取控件

时间:2011-07-31 22:09:51

标签: .net wpf mvvm parent-child

在我的viewModel中我可以使用

获取与之关联的窗口
var windows = Application.Current.Windows;
            for (var i = 0; i < windows.Count; i++)
            {
                if (windows[i].DataContext == this)
                {
                   //                      
                }
            }

在这个窗口中有一个FlowDocument我需要在我的viewModel中引用它,我知道我有时可以破坏规则并编写一些代码隐藏,但是因为我有窗口并且这个控件包含/ child在这个窗口中我认为我可以在没有任何代码隐藏,任何建议的情况下完成它吗?

提前致谢

1 个答案:

答案 0 :(得分:1)

首先,如果您需要访问ViewModel中的UI元素,则不能以正确的方式使用MVVM。您应该考虑使用绑定(无论您正在做什么: - )

无论如何,您可以遍历可视树以查找Window的后代。但是,FlowDocument不在可见树中,因为它是FrameworkContentElement,因此VisualTreeHelper将无效。

您需要合并VisualTreeHelperLogicalTreeHelper:可以在此处找到此实现:Find Element By Visual Tree

这是一个稍微重写的版本,像

一样使用它
if (windows[i].DataContext == this)
{
    var flowDocument = windows[i].FindChild<FlowDocument>();
}

<强> DependencyObjectExtensions.cs

public static class DependencyObjectExtensions
{
    public static T FindChild<T>(this DependencyObject source) where T : DependencyObject
    {
        if (source != null)
        {
            var childs = GetChildObjects(source);
            foreach (DependencyObject child in childs)
            {
                //analyze if children match the requested type
                if (child != null && child is T)
                {
                    return (T)child;
                }

                T descendant = FindChild<T>(child);
                if (descendant is T)
                {
                    return descendant;
                }
            }
        }
        return null;
    }
    public static IEnumerable<DependencyObject> GetChildObjects(this DependencyObject parent)
    {
        if (parent == null) yield break;

        if (parent is ContentElement || parent is FrameworkElement)
        {
            //use the logical tree for content / framework elements
            foreach (object obj in LogicalTreeHelper.GetChildren(parent))
            {
                var depObj = obj as DependencyObject;
                if (depObj != null) yield return (DependencyObject)obj;
            }
        }
        else
        {
            //use the visual tree per default
            int count = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < count; i++)
            {
                yield return VisualTreeHelper.GetChild(parent, i);
            }
        }
    }
}