У меня есть следующий код 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
.
Но я не уверен, как это сделать, есть идеи?
Вы можете легко переместить стиль в 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 в Style (или Dictionary), я предлагаю записать переменную Bindings непосредственно в Control, а остальное определить как 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}">
Экраны (пунктирные линии - линии сетки)
Редактировать
Чтобы установить Command
в Hyperlink
, мы используем свойство Command
кнопки для установки привязки. Поэтому мы должны добавить 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}">
Насколько я понял, ваша цель - уменьшить количество дублированного кода, верно? Может быть, я немного излишне увлечен и забыл упомянуть, что это решение может упростить два TextBlocks
и Hyperlink
вместо небольшой части стиля Hyperlink.Inlines
. Если это соответствует вашим потребностям, я обновлю свой ответ.
«Можно упростить» - можете ли вы уточнить и дать исчерпывающий ответ?
Обновлено, надеюсь, это объяснение более ясное и ответ на исходный вопрос.
Ваш код "Стиль кнопки" не работает - кнопка, дублированная как ссылка, просто не появляется вообще при запуске. Вы тестировали собственное решение?
Конечно, см. Экраны в ответе. Если ничего не отображается, возможно, проблема в привязке. Что-то отображается в консоли? Другой вопрос: планируете ли вы расширить эту сетку более чем на 2 записи? Если да, то во время выполнения? (Я спрашиваю, потому что другой подход с DataGrid может лучше соответствовать вашим потребностям, чем этот)
Другой вопрос, скажем, если я хочу передать команду (вместо жесткого кода <Hyperlink Command = "{ Binding Link}" CommandParameter = "{Binding}">
), возможно ли это?
Да, это возможно, см. Edit. Мы привязываем команду и параметр Hyperlink
к команде и параметру Button
. При этом он может (и должен) быть установлен вне стиля (если вы не установите его, команда для выполнения отсутствует и выдает ошибку).
Как это должно ответить на мой вопрос?