继承的WPF自定义控件不会继承父命令 [英] Inherited WPF custom control does not inherit parent Command

查看:125
本文介绍了继承的WPF自定义控件不会继承父命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个IconButton以便在WPF/XMAML中使用.它应该能够在顶部显示Icon MDL2 Assets字体,在底部显示文本.它应该具有默认的WPF工具栏按钮的外观.我决定创建一个自定义控件,该控件继承自默认的WPF按钮.

I've created a IconButton for use in WPF/XMAML. It should be able to display an Icon MDL2 Assets font on top and an text on bottom. It should have the appearance of an default WPF toolbar button. I decided to create a custom control which inherits from default WPF button.

因此,我创建了自定义控件,并为Text和某种程度上神秘的MDL2IconCode添加了Dependency属性:

So I created the custom control and added Dependency Properties for Text and the somehow cryptic MDL2IconCode:

public class IconButton : Button
{
  public static readonly DependencyProperty TextProperty;
  public static readonly DependencyProperty MDL2IconCodeProperty;

  public string Text
  {
    get { return (string)GetValue(TextProperty); }
    set { SetValue(TextProperty, value); }
  }


  public string MDL2IconCode
  {
    get { return (string)GetValue(MDL2IconCodeProperty); }
    set { SetValue(MDL2IconCodeProperty, value); }
  }


  static IconButton()
  {
    DefaultStyleKeyProperty.OverrideMetadata(typeof(IconButton),
                                             new FrameworkPropertyMetadata(typeof(IconButton)));

    TextProperty = DependencyProperty.Register("Text",
                                               typeof(string),
                                               typeof(IconButton),
                                               new PropertyMetadata("Button text", OnTextChanged));

    MDL2IconCodeProperty = DependencyProperty.Register("MDL2IconCode",
                                                       typeof(string),
                                                       typeof(IconButton),
                                                       new PropertyMetadata("\uf13e", OnIconTextChanged));
  }

  static void OnTextChanged(DependencyObject o,
                            DependencyPropertyChangedEventArgs e)
  {
    var iconButton = o as IconButton;
    if (iconButton == null)
    {
      return;
    }
    string newText = e.NewValue as string;
    iconButton.Text = newText;
  }

  static void OnIconTextChanged(DependencyObject o,
                                DependencyPropertyChangedEventArgs e)
  {
    var iconButton = o as IconButton;
    if (iconButton == null)
    {
      return;
    }

    string newText = e.NewValue as string;
    iconButton.MDL2IconCode = newText;
  }
}

Generic.xaml 的ResourceDictionary看起来像这样:

The ResourceDictionary of Generic.xaml looks like this:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:UI.CustomControls">


  <Style TargetType="{x:Type local:IconButton}" 
         BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:IconButton}">
          <Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
            <StackPanel>
              <TextBlock HorizontalAlignment="Center"
                         Text="{TemplateBinding MDL2IconCode}"
                         FontFamily="Segoe MDL2 Assets"
                         FontSize="16"
                         x:Name="iconTextBlock"/>
              <TextBlock HorizontalAlignment="Center" 
                         Text="{TemplateBinding Text}"
                         x:Name="textTextBlock"/>
            </StackPanel>

          </Button>

        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

该按钮看起来应该正确.

The button looks as it should.

但是XAML中的命令绑定不再起作用.但是它应该可以工作,因为继承仍然是一个按钮.

But the command binding in XAML isn't working anymore. But it should work, as per inheritance it still is a button..

也许任何人都知道要添加什么以使命令绑定起作用?

Maybe anyone has an idea what to add to make the command binding work?

推荐答案

将控制模板内 Button 的命令绑定到模板化父级.

Bind the command of the Button inside of your control template to the templated parent.

<ControlTemplate TargetType="{x:Type local:IconButton}">
   <Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
           Command="{TemplateBinding Command}"
           CommandParameter="{TemplateBinding CommandParameter}"
           CommandTarget="{TemplateBinding CommandTarget}">
      <!-- ...other code. -->
   </Button>
</ControlTemplate>

但是它应该可以工作,因为继承仍然是一个按钮.

But it should work, as per inheritance it still is a button..

不.控件模板内部的 Button 不会神奇地绑定到其模板化父级的相应属性,无论它是从 Button 还是任何其他控件派生而来的.对于其他依赖项属性(例如 CommandParameter ),也必须这样做.

No. The Button inside of your control template does not magically bind to the corresponding properties of its templated parent, regardless if it is derived from Button or any other control. You will have to do so for other dependency properties like the CommandParameter as well.

另请注意, Binding 标记扩展名.因此,当 TemplateBinding 不起作用时,例如在双向绑定方案中,您可以像这样使用 TemplatedParent :

Please also note that TemplateBinding is an optimized binding that does not have all capabilities of the more powerful Binding markup extension. Consequently, when TemplateBinding does not work, e.g. in two-way binding scenarios, you can use TemplatedParent like this:

{Binding RelativeSource={RelativeSource TemplatedParent}, Path=MyDependencyProperty}

有关更多信息,您可以参考

For more information, you can refer to the TemplateBinding documentation.

这篇关于继承的WPF自定义控件不会继承父命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆