【问题标题】:Get control from property name in viewmodel using Caliburn Micro使用 Caliburn Micro 从视图模型中的属性名称获取控制权
【发布时间】:2014-06-07 21:25:24
【问题描述】:

我想获得对绑定到给定属性名称的TextBox 的引用。 我想在不改变视图的情况下做到这一点。 有没有使用 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 = ...
        };
    }
}

【问题讨论】:

  • 你的最终目标是什么?您的ViewModel 似乎不应该在这种程度上知道您的View,您可能可以采取另一种方法。可能这确实是解决您的问题的唯一方法,但绝对值得探索您想要实现的目标。
  • 我是 WPF 初学者,所以这很可能是错误的方法。这个想法是为继承视图模型中的属性标记属性提供自动验证,而无需调整视图。设置自动验证相对简单。我遇到的问题是准确控制它的行为方式。我的想法是访问映射到属性更改的视图事件(通过TextBox)。 IE。如果有人在视图中执行此操作,请验证该字段。
  • 啊,我明白了,大概您还需要定义这些错误将如何显示在您的视图中?这可能有一些有用的信息:blog.magnusmontin.net/2013/08/26/data-validation-in-wpf 再说一次,它可能不是 =D
  • @Chris 是的,如果您想自定义错误显示,您可以更改视图中的 Validation.ErrorTemplate。还有一个合理的红色边框默认值。

标签: c# wpf caliburn.micro


【解决方案1】:

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

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

使用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;
    };

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

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

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

你必须小心 null/sanity 检查。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    相关资源
    最近更新 更多