【问题标题】:Converting a UserControl to a Custom Control将用户控件转换为自定义控件
【发布时间】:2012-04-27 13:39:28
【问题描述】:

下面的 UserControl 效果很好,但我想让更改样式更容易。

我尝试过的一件事是将其转换为自定义控件,但我一直停留在基础知识上,例如如何在处理属性更改的静态方法中设置 ToolTip(见下文)

我尝试将样式移动到 ResourceDictionary 中的通用按钮样式的另一件事,但这是这个问题的主题

如何在子类按钮中设置工具提示?

干杯

用户控件 XAML:

<UserControl.Resources>
    <ResourceDictionary Source="pack://application:,,,/Smack.Core.Presentation.Wpf;component/Themes/generic.xaml" />
</UserControl.Resources>

<Button x:Name="_button" Style="{StaticResource blueButtonStyle}" Command="{Binding AddNewItemCommand}"  >
    <StackPanel Orientation="Horizontal" >
        <Image Source="{resx:Resx ResxName=Smack.Core.Presentation.Resources.MasterDetail, Key=bullet_add}" Stretch="Uniform" VerticalAlignment="Center" />
        <AccessText x:Name="_accesText" VerticalAlignment="Center">_Add New Subject</AccessText>
        <ContentPresenter/>
    </StackPanel>
</Button>

用户控制代码背后:

public partial class AddNewItemButton : UserControl
{
    public AddNewItemButton() { InitializeComponent(); }

    public static readonly DependencyProperty SubjectProperty = DependencyProperty.Register(
        "Subject", typeof (string), typeof (AddNewItemButton),
        new FrameworkPropertyMetadata(OnSubjectChanged));

    public string Subject { get { return (string) GetValue(SubjectProperty); } set { SetValue(SubjectProperty, value); } }

    private static void OnSubjectChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) {
        var control = obj as AddNewItemButton;
        if (control == null) return;

        control._accesText.Text = "_" + string.Format(MasterDetail.Subject_AddNew_Label, control.Subject.Capitalize());

        control._button.ToolTip = string.Format(MasterDetail.Subject_AddNew_ToolTip, control.Subject.ToLower());
    }

}

尝试创建自定义控件失败:

public class MyButton : Button
{
    public static readonly DependencyProperty SubjectProperty = DependencyProperty.Register(
        "ItemName", typeof(string), typeof(MyButton),
        new FrameworkPropertyMetadata(OnSubjectChanged));

    public string Subject
    {
        get { return (string)GetValue(SubjectProperty); }
        set { SetValue(SubjectProperty, value); }
    }

    private static void OnSubjectChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        var control = obj as MyButton;
        if (control == null) return;

        ToolTip = ??;
    }
}

更新

根据 Phil 的回答,控件(底部的)比我想要的更“不美观”:--)

结果

代码

 public class AddNewItemButton : Button
{
    static AddNewItemButton() {
        var type = typeof (AddNewItemButton);
        DefaultStyleKeyProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(type));
    }

    #region Subject

    public static readonly DependencyProperty SubjectProperty = DependencyProperty.Register(
        "Subject", typeof(string), typeof(AddNewItemButton),
        new PropertyMetadata(default(string)));

    public string Subject
    {
        get { return (string)GetValue(SubjectProperty); }
        set { SetValue(SubjectProperty, value); }
    }

    #endregion

}

Generic.xaml

<Style TargetType="{x:Type local:AddNewItemButton}">

    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Subject, Converter={StaticResource AddNewItemForToolTip}}"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:AddNewItemButton}">
                <Border Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>

                        <Image Stretch="Uniform" VerticalAlignment="Center"
                            Source="{resx:Resx ResxName=Smack.Core.Presentation.Resources.MasterDetail, Key=bullet_add}" />

                        <AccessText 
                            Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Subject, Converter={StaticResource AddNewItemForLabel}}" />

                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

【问题讨论】:

    标签: c# .net wpf user-controls custom-controls


    【解决方案1】:

    这是一个带有工具提示的自定义按钮示例(基于您最近提出的问题):

    这是代码

    public class CustomButton : Button
    {
        static CustomButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomButton), 
               new FrameworkPropertyMetadata(typeof(CustomButton)));
        }
    
        public static readonly DependencyProperty SubjectProperty =
            DependencyProperty.Register("Subject", typeof (string),
            typeof (CustomButton), new PropertyMetadata(default(string)));
    
        public string Subject
        {
            get { return (string) GetValue(SubjectProperty); }
            set { SetValue(SubjectProperty, value); }
        }
    }
    

    这在 Themes/generic.xaml 中

    <System:String x:Key="Test">Add new: </System:String>
    
    <Style TargetType="{x:Type local:CustomButton}">
        <Setter Property="ToolTip" 
                Value="{Binding RelativeSource={RelativeSource Self}, Path=Subject}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomButton}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
    
                            <Label Grid.Column="0" Content="Image here" 
                                   VerticalAlignment="Center" Padding="0,0,5,0"/>
    
                            <AccessText Grid.Column="1" VerticalAlignment="Center">
                                <AccessText.Text>
                                    <MultiBinding StringFormat="{}_{0} {1}">
                                        <Binding Source="{StaticResource Test}"/>
                                        <Binding RelativeSource=
                                            "{RelativeSource TemplatedParent}" 
                                            Path="Subject"/>
                                    </MultiBinding>
                                </AccessText.Text>
                            </AccessText>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    【讨论】:

    • 感谢您在使用不同技术方面的帮助。我无法让自定义控件做很多事情,但发布了我的代码(请参阅更新后的帖子),希望有一些明显的东西跳出来。干杯
    • 用于其他目的,但绑定 {RelativeSource TemplatedParent} 对我来说很受欢迎。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2011-12-30
    • 2011-09-10
    • 2017-08-29
    • 2014-02-20
    • 1970-01-01
    相关资源
    最近更新 更多