简体   繁体   English

WPF使用StaticResource封装矩形以填充到WPF中的CustomControl

[英]WPF Encapsulate rectangle with StaticResource as fill to a CustomControl in WPF

I am using ModernUIIcons that come with MahApps.Metro in a Xaml file as StaticResources. 我在Xaml文件中使用MahApps.Metro随附的ModernUIIcons作为StaticResources。 To put one in my UI is very easy, like this: 在我的用户界面中放置一个非常简单,如下所示:

<Rectangle  Width="19" 
            Height="19">
   <Rectangle.Fill>
      <VisualBrush Visual="{StaticResource appbar_database}" />
   </Rectangle.Fill>
</Rectangle>

I want to encapsulate all the logic of the rectangle in a CustomControl so I can do something like the following: 我想将矩形的所有逻辑封装在CustomControl中,以便可以执行以下操作:

<cc:MenuItemIcon Source="{StaticResource appbar_page}"/>

This is what I got so far: 这是我到目前为止所得到的:

In one project as library, Themes/Generic.xaml: 在一个作为库的项目中,Themes / Generic.xaml:

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

<Style TargetType="{x:Type local:MenuItemIcon}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MenuItemIcon}">
                <Rectangle  Width="19" 
                            Height="19">
                    <Rectangle.Fill>
                        <VisualBrush Visual="{TemplateBinding Source}" />
                    </Rectangle.Fill>
                </Rectangle>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</ResourceDictionary>

And in the CS file 并在CS文件中

namespace AMIGEDM.CustomControls.Menu
{
   public class MenuItemIcon : Control
{
   static MenuItemIcon()
   {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(MenuItemIcon), new  FrameworkPropertyMetadata(typeof(MenuItemIcon)));
   }

   public static readonly DependencyProperty SourceProperty =
      DependencyProperty.Register("Source", typeof(Visual), typeof(MenuItemIcon));

   public Visual Source
   {
      get { return (Visual)GetValue(SourceProperty); }
      set { SetValue(SourceProperty, value); }
   }
  }
}

Everything compiles silky smooth, so I go to my TestDummy Project 一切都能如丝般顺滑地编译,所以我去了我的TestDummy项目

<Window x:Class="AMIGEDM.TestDummy.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:cc="clr-namespace:AMIGEDM.CustomControls.Menu;assembly=AMIGEDM.CustomControls">
<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/AMIGEDM.TestDummy;component/Resources/Icons.xaml"/>
            <ResourceDictionary Source="pack://application:,,,/AMIGEDM.CustomControls;component/Themes/Generic.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>
<Grid>
    <Menu IsMainMenu="True" SnapsToDevicePixels="True">
        <MenuItem Header="_Open">
            <MenuItem Header="_File">
                <MenuItem.Icon>
                    <cc:MenuItemIcon Source="{StaticResource appbar_page}"/>
                </MenuItem.Icon>
            </MenuItem>
            <MenuItem Header="_File">
                <MenuItem.Icon>
                    <Rectangle  Width="19" 
                            Height="19">
                        <Rectangle.Fill>
                            <VisualBrush Visual="{StaticResource appbar_database}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </MenuItem.Icon>
            </MenuItem>
        </MenuItem>
    </Menu>
</Grid>

The Library puts the Icon using the Rectangle, Rectangle Fill and VisualBrush, but when I try to use the CustomControl it shows nothing 库使用Rectangle,Rectangle Fill和VisualBrush放置Icon,但是当我尝试使用CustomControl时,它什么也没显示

如您所见,该图标使用完整的矩形显示,但不包含我的自定义控件

All the code looks normal, except for the style of MenuItemIcon . 除了MenuItemIcon的样式外,所有代码看起来都很正常。 Quote about TemplateBinding from Adam Nathan book: 引用亚当·内森(Adam Nathan)的书中有关TemplateBinding内容:

TemplateBinding doesn't work outside a template or outside its VisualTree property, so you can't even use TemplateBinding inside a template's trigger. TemplateBinding在模板外部或其VisualTree属性外部不起作用,因此您甚至不能在模板的触发器内使用TemplateBinding。 Furthermore, TemplateBinding doesn't work when applied to a Freezable (for mostly artificial reasons). 此外,将TemplateBinding应用于Freezable时不起作用(主要是出于人工原因)。

And quote from MSDN about VisualBrush : 并从MSDN引用有关VisualBrush

Freezable Features: Because it inherits from the Freezable class, the VisualBrush class provides several special features: VisualBrush objects can be declared as resources and shared among multiple objects. Freezable功能:因为它继承自Freezable类,所以VisualBrush类提供了几个特殊功能:VisualBrush对象可以声明为资源并在多个对象之间共享。

Therefore instead of: 因此,代替:

<VisualBrush Visual="{TemplateBinding Source}" />

Use the construction {RelativeSource TemplatedParent} and a Path equal to the dependency property whose value you want to retrieve: 使用构造{RelativeSource TemplatedParent}和一个Path等于要检索其值的依赖项属性:

<Style TargetType="{x:Type local:MenuItemIcon}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MenuItemIcon}">
                <Rectangle Width="22" Height="22">
                    <Rectangle.Fill>
                        <VisualBrush Visual="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Source}" />                                
                    </Rectangle.Fill>
                </Rectangle>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM