我为带有图像的按钮创建了一个样式:
<Style x:Key="StyleButtonBase" TargetType="Button">
<Style.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Sizes/Sizes.xaml" />
<ResourceDictionary Source="../Colors/Brushes.xaml" />
<ResourceDictionary Source="../Fonts/Fonts.xaml" />
<ResourceDictionary Source="../Images/Images.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BrushButtonActive}" />
<Setter Property="Foreground" Value="{StaticResource BrushForegroundLight}" />
<Setter Property="FontFamily" Value="{StaticResource FontFamilyDefault}" />
<Setter Property="FontSize" Value="{StaticResource DoubleFontSizeStandard}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{StaticResource BrushBorder}"
BorderThickness="{StaticResource ThicknessBorder}"
CornerRadius="{StaticResource CornerRadius}">
<Image Source="{StaticResource IconIcon}" Stretch="None" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource BrushButtonPressed}" />
</Trigger>
</Style.Triggers>
</Style>
现在我想创建一个User-Control,它只包含一个具有此样式的Button和一个Dependency属性来设置Button Image。我的用户控件的XAML部分如下所示:
<UserControl
x:Class="HH.HMI.ToolSuite.ResourceLib.Controls.ButtonSmall">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Styles/Buttons.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Button Style="{StaticResource StyleButtonBase}" Width="{StaticResource DoubleWidthButtonSmall}" Height="{StaticResource DoubleHeightControls}">
</Button></UserControl>
我的用户控件背后的代码如下所示:
public partial class ButtonSmall : UserControl, INotifyPropertyChanged
{
public ButtonSmall()
{
InitializeComponent();
}
public static readonly DependencyProperty ButtonImageProperty
= DependencyProperty.Register("ButtonImage", typeof(ImageSource), typeof(TextOutput), new PropertyMetadata(null, OnButtonImagePropertyChanged));
private static void OnButtonImagePropertyChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
ButtonSmall temp = dependencyObject as ButtonSmall;
temp.OnPropertyChanged("ButtonImage");
temp.OnButtonImagePropertyChanged(e);
}
private void OnButtonImagePropertyChanged(DependencyPropertyChangedEventArgs e)
{
ButtonSmallImage.Source = ButtonImageSource;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public ImageSource ButtonImageSource
{
get { return (ImageSource)GetValue(ButtonImageProperty); }
set { SetValue(ButtonImageProperty, value); }
}
}
在我的其他用户控件中,我通常访问用户控件本身的元素,如:
xamlname.text = text
现在我还没有用户控件的xaml代码中的命名元素。相反,我在样式中有命名元素,我在用户控件中引用它。如何通过我的代码访问这个?
答案 0 :(得分:1)
如果我是你,我会将Button子类化并创建一个新类(只是一个.cs文件),如下所示:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace MyProject
{
public class IconButton : Button
{
public static readonly DependencyProperty ButtonImageProperty = DependencyProperty.Register("ButtonImage", typeof(ImageSource), typeof(IconButton),
new FrameworkPropertyMetadata(new BitmapImage(), FrameworkPropertyMetadataOptions.AffectsRender));
public ImageSource ButtonImage
{
get { return (ImageSource)GetValue(ButtonImageProperty); }
set { SetValue(ButtonImageProperty, value); }
}
}
}
这意味着您现在可以引用该属性。否则,因为你的按钮只是一个常规按钮(只有常规按钮的属性;没有图像),你的风格并不知道你期望Button有的新图像属性。不要忘记更新你的风格的TargetType指向IconButton。
如果您将样式放在用户控件的资源部分,可以像这样设置按钮样式:
<UserControl x:Class="MyProject.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myclass="clr-namespace:MyProject">
<UserControl.Resources>
<!-- your style here -->
</UserControl.Resources>
<myclass:IconButton Style="{StaticResource StyleButtonBase}/>
</UserControl>
(必须更换xmlns&#39; myclass&#39;以引用自定义按钮所在的命名空间!)
此外,如果从样式中删除x:Key属性,它将应用于范围中的所有按钮,这意味着您可以省略显式设置。如果您在共享的ResourceDictionary中找到它(如果您正在构建自定义控件库),这可能很方便(如果您这样做,则需要在App.xaml.cs文件中组合此资源字典) )。如果您最终这样做并且发现您的UserControl除了包装IconButton之外没有任何特殊功能,您当然可以完全省略它并且只在其他控件中直接使用IconButtons。你的样式声明你的IconButton看起来如何,你的IconButton类确保你的样式所期望的资源(你的图像)在运行时查找它们,所以只要你的风格在范围内,你就会好走。
答案 1 :(得分:0)
如果样式在App.xaml中的Application.Resources
中定义,或者在App.xaml中合并到Application.Resources
的资源字典中定义,则可以在用户控件中引用它通过StaticResource
。如果它在另一个资源字典中,您必须将该合并到UserControl.Resources
。
或者您可以将其直接放在UserControl.Resources
中,如TernaryTopiary所示,如果在其他地方不需要它。
对于图像源属性,您可以像Ternary建议的那样编写一个Button子类,或者您可以编写一个附加属性(见下文)。在XAML中,当您自定义控件时,首先尝试使用常规属性;然后你试着重新开始。然后你升级到替换控制模板,并且不能完成这项工作,你考虑附加的属性/行为。只有在所有其他方法都失败的情况下才会使用子类化。你应该知道如何去做,但你也应该学习其他的做事方式。
在这种情况下,有一种快速而肮脏的方式可以做到与正确的XAML操作方式一致:按钮的Content
属性未使用,并且它的声明类型是Object
,所以我们可以使用它。由于我们使用绑定传递图像源,因此您可以摆脱PropertyChanged
上的ButtonImageSource
处理程序。
<UserControl
...>
<!-- ... -->
<Button
Content="{Binding ButtonImageSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
Style="{StaticResource StyleButtonBase}"
Width="{StaticResource DoubleWidthButtonSmall}"
Height="{StaticResource DoubleHeightControls}"
/>
在StyleButtonBase
中的控件模板中进行以下更改:
<ControlTemplate TargetType="Button">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{StaticResource BrushBorder}"
BorderThickness="{StaticResource ThicknessBorder}"
CornerRadius="{StaticResource CornerRadius}"
>
<!-- Now we'll find the image source in the button's Content --->
<Image
Source="{TemplateBinding Content}"
Stretch="None"
/>
</Border>
</ControlTemplate>
使用Content
对此非常轻微地滥用WPF:您不应该真正重新利用属性。 WPF中普遍理解Content
是指&#34;任意内容&#34;,而不是&#34;任何ImageSource
&#34;。
所以它更多一点&#34;正确&#34;使用附属物,并没有太多的工作。这就是看起来的样子。
我们会在一个单独的静态类中定义附加属性,因为除了ButtonImageSource
之外我无法想到它的好名称,您已经在SmallButton
中使用了public static class ButtonHelper
{
#region ButtonHelper.ButtonImageSource Attached Property
public static ImageSource GetButtonImageSource(Button obj)
{
return (ImageSource)obj.GetValue(ButtonImageSourceProperty);
}
public static void SetButtonImageSource(Button obj, ImageSource value)
{
obj.SetValue(ButtonImageSourceProperty, value);
}
public static readonly DependencyProperty ButtonImageSourceProperty =
DependencyProperty.RegisterAttached("ButtonImageSource", typeof(ImageSource), typeof(ButtonHelper),
new PropertyMetadata(null));
#endregion ButtonHelper.ButtonImageSource Attached Property
}
{1}}:
Content
在XAML中,用户控件使用此附加属性而不是<Button
Style="{StaticResource StyleButtonBase}"
local:ButtonHelper.ButtonImageSource="{Binding ButtonImageSource, RelativeSource={RelativeSource AncestorType=UserControl}}"
/>
:
<ControlTemplate TargetType="Button">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4"
>
<Image
Source="{TemplateBinding local:ButtonHelper.ButtonImageSource}"
Stretch="None"
/>
</Border>
</ControlTemplate>
控制模板同样如此:
Content
所有附加的属性确实为我们提供了一个名为ImageSource
的属性,并且强类型为typeof(TextOutput)
,我们可以使用它来传递该图像源。
另一件事:也许这是一个错误,当你简化问题的代码时会悄悄进入,但是你将DependencyProperty.Register()
传递给typeof(ButtonSmall)
你应该传递的ButtonImage
ButtonImageSource
}。更重要的是,您应该为单个属性设置两个名称:public static readonly DependencyProperty ButtonImageSourceProperty
= DependencyProperty.Register(
"ButtonImageSource",
typeof(ImageSource),
// Should be ButtonSmall, not TextOutput
typeof(ButtonSmall),
new PropertyMetadata(null));
public ImageSource ButtonImageSource
{
get { return (ImageSource)GetValue(ButtonImageSourceProperty); }
set { SetValue(ButtonImageSourceProperty, value); }
}
和TemplateBinding
。
BorderBrush
顺便说一下,在你的风格中,最好将BorderThickness
用于Background
和 describe('your block', () => {
let submitB;
beforeEach(() => {
submitB = fixture.debugElement.nativeElement.query(By.css('#submitNewPage'));
submitB.dispatchEvent(new Event('click'))
});
it('your expectation' () => {})
})
,并设置样式设置器中的默认值,就像{{1 }}。