xaml - 将属性绑定到 ResourceDictionary 中定义的样式以消除代码重复
问题描述
我有以下 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 放入样式(或字典)中,而是将变量 Binding 直接写入控件并将其余部分定义为样式。
更具体:以下标记将绑定字符串显示为Hyperlink
单击时执行 ICommand 的 a。
<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}">
屏幕(虚线是网格线)
编辑
我们使用Button的Command
Property来设置Binding 。因此我们必须在我们的样式中添加一个。将“硬编码”替换为. 对命令参数执行相同的操作。Hyperlink
Command
TemplateBinding
Command
TemplateBinding
Button
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}">
推荐阅读
- c# - 如何解决在 Xamarin Forms 新导入的 Nuget 包上导入的多个程序集
- javascript - 我的讲师分配给我的 6 个 JavaScript 任务
- python - 在 python 中使用 sqlalchemy 连接到 postgres 时在哪里提到架构
- sorting - 如何编写脚本以使用公式自动对列进行排序并在每次更改时更新?
- python - 样本数据脚本查询?
- netlify - 如何在 netlify 上提供 robots.txt 和 sitemap.xml?
- github - 有什么方法可以配置 GitHub 或 ArgoCd 以获取在 JFrog Artifactory 中完成的任何更新的通知?
- node.js - Node.js 关于缓冲区、流、管道、axios、createWriteStream 和 createReadStream 的混淆
- datetime - Elasticsearch NEST 客户端日期时间反序列化
- reactjs - 在 JSX 文件中的空标签 <> 之后需要语法高亮帮助