Свяжите свойства со стилями, определенными в ResourceDictionary, чтобы устранить дублирование кода - PullRequest
0 голосов
/ 02 мая 2018

У меня есть следующий код 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 (<Hyperlink.Inlines> и т. Д.). Я хочу реорганизовать его так, чтобы исключить дублирование кода. Для этого я подумываю определить стиль <Hyperlink.Inlines> в ResourceDictionary и затем связать его с соответствующими свойствами в MainWindowVM.

Но я не уверен, как это сделать, есть идеи?

1 Ответ

0 голосов
/ 02 мая 2018

Вы можете легко переместить стиль в 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 непосредственно в элемент управления и определить остальные как Style.

Более конкретно: следующая разметка отображает связанную строку в виде 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}">

Экраны (пунктирные линии - линии сетки)

Runtime

Редактировать

Чтобы установить Command для Hyperlink, мы используем Command свойство Button для установки привязки. Поэтому мы должны добавить TemplateBinding в нашем стиле. Замените «Жесткий код» Command на TemplateBinding на Button Command. Сделайте то же самое для параметра Command.

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

И установите Command и CommandParameter в стиле Button

    <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}">
...