Converting a UserControl to a Custom Control

我的未来我决定 提交于 2019-12-10 10:31:49

问题


The UserControl below works well but I would like to make it easier to change the Style.

One thing I have tried is to convert this to a Custom Control, but I am stuck on basics like how to set the ToolTip inside the static method that deals with a change in a property (see below)

The other thing I tried to move the Style into a generic button style in the ResourceDictionary, but that is the subject of this question

How can I set the ToolTip in my subclassed Button?

Cheers

UserControl 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>

UserControl Code Behind:

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());
    }

}

Failed attempt to create a Custom Control:

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 = ??;
    }
}

UPDATE

Based on Phil's answer, the control (the bottom one) is more 'lookless' than I'd like :--)

Result

Code

 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>


回答1:


Here's an example of a custom button with a tooltip (based on the questions you've been asking recently):

This is the code

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); }
    }
}

This goes in 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>


来源:https://stackoverflow.com/questions/10351682/converting-a-usercontrol-to-a-custom-control

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!