c# - 使用 Caliburn Micro 从 View 模型中的属性名称获取控制权

标签 c# wpf caliburn.micro

我想获取对绑定(bind)到给定属性名称的 TextBox 的引用。 我想在不改变 View 的情况下这样做。 是否有使用 Caliburn Micro 执行此操作的正确方法? 如果不是,什么是“足够好”的方式?

public class MweViewModel : PropertyChangedBase
{
    public MweViewModel() : base()
    {
        PropertyChanged += (object sender, PropertyChangedEventArgs e) =>
        {
            // Find control (i.e. TextBox) bound to property with name e.PropertyName
            TextBox textBox = ...
        };
    }
}

最佳答案

我不确定这是最明智的方法(这不是我自己尝试做的事情),查看 Documentation ,提到了一个 ViewModelBinder 类,它负责将属性、方法等的各种绑定(bind)固定到它们各自的 ViewModels

ViewModelBinder 上的 BindProperties 函数负责解析您的属性与它们最终绑定(bind)到的 UI 元素之间的绑定(bind)。您可以根据现有代码定义您自己的函数,该函数会跟踪所有正在建立的绑定(bind),因此您将拥有它们的记录,您可以在程序的其他地方使用它们。

使用 existing code会给你这样的东西:

ViewModelBinder.BindProperties = (namedElements, viewModelType) =>
    {
        var unmatchedElements = new List<FrameworkElement>();

        foreach (var element in namedElements)
        {
            var cleanName = element.Name.Trim('_');
            var parts = cleanName.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);

            var property = viewModelType.GetPropertyCaseInsensitive(parts[0]);
            var interpretedViewModelType = viewModelType;

            for (int i = 1; i < parts.Length && property != null; i++)
            {
                interpretedViewModelType = property.PropertyType;
                property = interpretedViewModelType.GetPropertyCaseInsensitive(parts[i]);
            }

            if (property == null)
            {
                unmatchedElements.Add(element);
                // Log.Info("Binding Convention Not Applied: Element {0} did not match a property.", element.Name);
                continue;
            }

            var convention = ConventionManager.GetElementConvention(element.GetType());
            if (convention == null)
            {
                unmatchedElements.Add(element);
                // Log.Warn("Binding Convention Not Applied: No conventions configured for {0}.", element.GetType());
                continue;
            }

            var applied = convention.ApplyBinding(
                interpretedViewModelType,
                cleanName.Replace('_', '.'),
                property,
                element,
                convention
                );

            if (applied)
            {
                // Log.Info("Binding Convention Applied: Element {0}.", element.Name);
            }
            else
            {
                // Log.Info("Binding Convention Not Applied: Element {0} has existing binding.", element.Name);
                unmatchedElements.Add(element);
            }
        }

        return unmatchedElements;
    };

在添加绑定(bind)时(设置 applied 时),您拥有所需的所有信息。然后您可以存储特定的绑定(bind)(例如与 TextBox 相关的绑定(bind))。

您可以使用静态字典之类的东西(根据您的要求,可能会有更合适的东西):

        ViewModel Type    Bound Property      List of Bound elements
             |                   |                      |
             |                   |                      |
Dictionary<Type, Dictionary<PropertyInfo, List<FrameworkElement>>>

您必须小心进行空值/健全性检查。

还有一些其他解决方案使用辅助方法来获取绑定(bind)的属性/控件,尽管它们通常必须遍历可视化树,通过这种方式,您可以在实际创建绑定(bind)时执行此操作。

关于c# - 使用 Caliburn Micro 从 View 模型中的属性名称获取控制权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24048391/

相关文章:

c# - XAML 中列表的绑定(bind)列表?

c# - 如何在WPF中捏

c# - 是否可以找到 View 模型引用的属性

c# - Caliburn.Micro - 是否可以将事件绑定(bind)到 System.Action 或任何其他委托(delegate)?

c# - 使用 Kinect 在 InkCanvas WPF 中绘制平滑线条

c# - ASP.NET Web API 模型绑定(bind) - 不同的参数名称

c# - AvalonEdit WPF 文本编辑器 (SharpDevelop) : How to highlight a specific range of text?

c# - 字符串未被识别为有效的日期时间,当它出现时?

c# - 显示传递对象的异步套接字示例?

viewmodel - Caliburn.Micro ViewModel 和 ActivateItem - 在当前上下文中不存在