【问题标题】:Bind properties to styles defined at ResourceDictionary to eliminate code duplication将属性绑定到 ResourceDictionary 中定义的样式以消除代码重复
【发布时间】:2018-05-02 03:28:57
【问题描述】:

我有以下 XAML 代码:

<Window x:Class="LinkButton.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LinkButton"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{StaticResource MainWindowVM}">

    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Margin" Value="10" />
        </Style>
    </Window.Resources>

    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0" Text="ddk" />
        <TextBlock Grid.Row="0" Grid.Column="1" >
             <Hyperlink Command="{Binding Link}"  
                       CommandParameter="{Binding}"
                       Foreground="Blue" >
               <Hyperlink.Inlines>
                   <TextBlock>
                        <TextBlock.Style>
                            <Style>
                                <Setter Property="TextBlock.Text" Value="{Binding Description01.Header}" />
                            </Style>
                        </TextBlock.Style>
                   </TextBlock>
               </Hyperlink.Inlines>
                </Hyperlink>
        </TextBlock>
        <TextBlock Grid.Row="1" Grid.Column="0" Text="dde" />
        <TextBlock Grid.Row="1" Grid.Column="1">
            <Hyperlink Command="{Binding Link}"  
                       CommandParameter="{Binding}"
                       Foreground="Blue" >
               <Hyperlink.Inlines>
                   <TextBlock>
                        <TextBlock.Style>
                            <Style>
                                <Setter Property="TextBlock.Text" Value="{Binding Description11.Header}" />
                            </Style>
                        </TextBlock.Style>
                   </TextBlock>
               </Hyperlink.Inlines>
                </Hyperlink>
        </TextBlock>
    </Grid>
</Window>

以及C#代码代码:

public class TestCommand : ICommand
{
    public delegate void ICommandOnExecute(object parameter);
    public delegate bool ICommandOnCanExecute(object parameter);

    private ICommandOnExecute _execute;
    private ICommandOnCanExecute _canExecute;

    public TestCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod)
    {
        _execute = onExecuteMethod;
        _canExecute = onCanExecuteMethod;
    }

    #region ICommand Members

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute.Invoke(parameter);
    }

    public void Execute(object parameter)
    {
        _execute.Invoke(parameter);
    }

    #endregion
}

public class LongDescription
{
    public string Header { get; }
    public string Description { get; }
    public LongDescription(string header, string description)
    {
        Header = header;
        Description = description;
    }
}

public class MainWindowVM
{



    public ICommand Link => new TestCommand(ExecuteCommand1, CanExecuteCommand1);

    public LongDescription Description11 => new LongDescription("cell11", "result cell11");
    public LongDescription Description01 => new LongDescription("cell01", "result cell01");

    public bool CanExecuteCommand1(object parameter)
    {
        return true;
    }

    public void ExecuteCommand1(object parameter)
    {
        MessageBox.Show("Executing command 1");
    }

}

很明显,我在 XAML 中重复了代码(&lt;Hyperlink.Inlines&gt; 等)。我想重构它,以便消除代码重复。为此,我正在考虑在ResourceDictionary 中定义样式&lt;Hyperlink.Inlines&gt;,然后将其绑定到MainWindowVM 中的适当属性。

但我不确定该怎么做,有什么想法吗?

【问题讨论】:

    标签: xaml resourcedictionary


    【解决方案1】:

    您可以像这样轻松地在 ResourceDictionary 中移动样式

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
        <!-- Key is required to identify the Style -->
        <Style x:Key="Bind01" TargetType="TextBlock">
            <Setter Property="Text" Value="{Binding Description01.Header}" />
        </Style>
    
        <Style x:Key="Bind11" TargetType="TextBlock">
            <Setter Property="Text" Value="{Binding Description11.Header}" />        
        </Style>
    </ResourceDictionary>
    

    并在您的窗口中合并字典以使用样式

    合并

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="YourDictionaryHere"/>
            </ResourceDictionary.MergedDictionaries>
    
        <Style TargetType="TextBlock">
            <Setter Property="Margin" Value="10" />
        </Style>
        </ResourceDictionary>
    </Window.Resources>
    

    使用

    <TextBox Style="{DynamicResource Bind01}"/>
    

    简化

    我建议不要将变量 Binding 放入样式(或字典)中,而是将变量 Bindings 直接写入控件并将其余部分定义为样式。

    更具体:以下标记将绑定字符串显示为Hyperlink,单击时执行 ICommand。

        <TextBlock>
            <Hyperlink Command="{Binding Link}"  
                       CommandParameter="{Binding}"
                       Foreground="Blue" >
               <Hyperlink.Inlines>
                   <TextBlock>
                        <TextBlock.Style>
                            <Style>
                                <Setter Property="TextBlock.Text" Value="{Binding Description11.Header}" />
                            </Style>
                        </TextBlock.Style>
                   </TextBlock>
               </Hyperlink.Inlines>
                </Hyperlink>
        </TextBlock>
    

    我们可以改为为一个看起来(和做)相同的按钮定义一个样式,但变量 Binding 可以直接通过Content 设置。

    按钮样式

        <Style x:Key="LinkStyle" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <TextBlock>
                            <Hyperlink Command="{Binding Link}" CommandParameter="{Binding}">
                                <Run Text="{TemplateBinding Content}"/>
                            </Hyperlink>
                        </TextBlock>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    将样式应用于网格中的元素(将 TextBlock 替换为样式按钮)

        <TextBlock Grid.Row="0" Grid.Column="0" Text="ddk" />
        <Button Grid.Row="1" Grid.Column="1" 
                Content="{Binding Description01.Header}" 
                Style="{DynamicResource LinkStyle}">
        <TextBlock Grid.Row="1" Grid.Column="0" Text="dde" />
        <Button Grid.Row="1" Grid.Column="1" 
                Content="{Binding Description11.Header}" 
                Style="{DynamicResource LinkStyle}">
    

    屏幕(虚线是网格线)

    编辑

    要设置HyperlinkCommand,我们使用按钮的Command 属性来设置绑定。因此,我们必须在样式中添加TemplateBinding。将“硬编码”Command 替换为 TemplateBindingButton Command。对 Command 参数执行相同操作。

                 <Hyperlink Command="{TemplateBinding Command}"  
                       CommandParameter="{Templatebinding Commandparameter}"
                       Foreground="Blue" >
    

    并在样式Button中设置CommandCommandParameter

        <TextBlock Grid.Row="0" Grid.Column="0" Text="ddk" />
    <Button Grid.Row="1" Grid.Column="1" 
            Content="{Binding Description01.Header}"
            Command="{Binding YOURCOMMANDHERE}"
            CommandParameter="{YOURPARAMETER}" 
            Style="{DynamicResource LinkStyle}">
    <TextBlock Grid.Row="1" Grid.Column="0" Text="dde" />
    <Button Grid.Row="1" Grid.Column="1" 
            Content="{Binding Description11.Header}"
            Command="{Binding YOUROTHERCOMMANDHERE}"
            CommandParameter="{YOUROTHERPARAMETER}"
            Style="{DynamicResource LinkStyle}">
    

    【讨论】:

    • 这应该如何回答我的问题?
    • 据我了解,您的目标是减少重复代码,对吗?也许我有点过分热情,忘了提到这个解决方案可以简化两个TextBlocksHyperlink,而不是Hyperlink.Inlines 的小样式部分。如果这不符合您的需求,请更新我的答案。
    • “可以简化”--你能详细说明并给出完整的答案吗?
    • 更新了,希望这个解释更清楚,回答原问题。
    • 您的代码“按钮样式”不起作用 - 按钮加倍作为链接根本不会在运行时出现。您是否测试了自己的解决方案?
    猜你喜欢
    • 2021-12-13
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 2014-05-23
    • 2018-06-09
    • 1970-01-01
    • 2020-02-11
    相关资源
    最近更新 更多