从代码中设置自定义MarkupExtension

Fre*_*lad 7 c# wpf markup xaml markup-extensions

如何MarkupExtension从代码中设置自定义?

您可以轻松地从Xaml设置.这同样适用于BindingDynamicResource.

<TextBox FontSize="{Binding MyFontSize}"
         Style="{DynamicResource MyStyle}"
         Text="{markup:CustomMarkup}"/>
Run Code Online (Sandbox Code Playgroud)

通过代码设置相同的值需要一些不同的方法

  1. 绑定:使用textBox.SetBinding或BindingOperations.SetBinding

    Binding binding = new Binding("MyFontSize");
    BindingOperations.SetBinding(textBox, TextBox.FontSizeProperty, binding);
    
    Run Code Online (Sandbox Code Playgroud)
  2. DynamicResource:使用SetResourceReference

    textBox.SetResourceReference(TextBox.StyleProperty, "MyStyle");
    
    Run Code Online (Sandbox Code Playgroud)
  3. CustomMarkup:如何MarkupExtension从代码中设置自定义?如果我打电话给ProvideValue那个案子,我怎么得到一个IServiceProvider?*

    CustomMarkupExtension customExtension = new CustomMarkupExtension();
    textBox.Text = customExtension.ProvideValue(??);
    
    Run Code Online (Sandbox Code Playgroud)

我在这个问题上发现了很少,所以可以做到吗?


HB回答了这个问题.只是在这里添加一些细节,为什么我想这样做.我试图为以下问题创建一个解决方法.

问题是,由于密封,您无法从中获取Binding和覆盖ProvideValue.您将不得不这样做:自定义WPF绑定标记扩展的基类.但问题是,当你返回a BindingSetter你得到一个异常,但在Style它之外它工作正常.

我已经在几个地方读过你应该返回它MarkupExtension自己,如果它TargetObject是一个Setter允许它一旦它被应用到一个实际的reeavaluate这是FrameworkElement有道理的.

但是,只有在TargetProperty类型有效时才有效object,否则异常返回.如果您查看源代码,BindingBase您可以看到它确实如此,但看起来框架有一些秘密成分使其工作.

H.B*_*.B. 6

我认为没有代码等价,服务只能通过XAML获得.来自MSDN:

MarkupExtension只有一个虚拟方法ProvideValue.输入serviceProvider参数是在XAML处理器调用标记扩展时将服务传递给实现的方式.


Fil*_*Fil 5

作为替代方案,它是在代码中生成的,但不一定像XAML那样优雅:

        var markup = new CustomMarkup();
        markup.ProvideValue(new Target(textBox, TextBox.TextProperty));
Run Code Online (Sandbox Code Playgroud)

Target的实现很简单:

public struct Target : IServiceProvider, IProvideValueTarget
{
    private readonly DependencyObject _targetObject;
    private readonly DependencyProperty _targetProperty;

    public Target(DependencyObject targetObject, DependencyProperty targetProperty)
    {
        _targetObject = targetObject;
        _targetProperty = targetProperty;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType == typeof(IProvideValueTarget))
            return this;
        return null;
    }

    object IProvideValueTarget.TargetObject { get { return _targetObject; } }
    object IProvideValueTarget.TargetProperty { get { return _targetProperty; } }
}
Run Code Online (Sandbox Code Playgroud)

唯一剩下的就是能够从XAML对象模型获取引用回"CustomMarkup".有了上述内容,您需要依赖它来引用它.