我有一个来自客户端的有趣请求,涉及到多个挑战,我认为最容易的一个,结果是最难的。XAML使用来自目标控件的绑定路径在样式设置器中绑定
用户需要知道某个值已在本地更改,但尚未保留到后端存储。 (脏状态)我们用一个数据触发器解决了页面上每个控件声明的风格。当值被改变时,控制背景将被填充为黄色,然后当按下保存按钮时,将其重置回控制默认值。
模型视图实现了自定义接口:ILocalValueCache这有应该返回布尔值,表明自上次数据刷新当前值已更改的索引。
- ModelView还实现IDataErrorInfo并使用DataAnnotations属性进行验证,所以我不能简单地使用验证模板。
我想什么做的是使用一个单一的样式或控件模板,这是困难的,因为每个控件现在有两个绑定,一个价值,另一个价值IsLocal简化XAML:
更具体地说,我更喜欢一个解决方案,开发人员不需要知道它的工作原理(xIsLocal标记的字段名称)的内部机制,或者绑定源甚至支持它。
因为ViewModel实现了这个接口(和IDataErrorInfo一样),所以我应该能够全局定位绑定到接口描述的状态的控件样式。
这里是XAML的一些文本框的一部分:
<TextBox Text="{Binding ScaleName}" Margin="5,2,5,2" Grid.Row="1" Grid.Column="2">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding ScaleNameIsLocal}" Value="True">
<Setter Property="Background" Value="{StaticResource LocalValueBackgroundBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox x:Name="nbScaleCap" Text="{Binding ScaleCap}" Grid.Row="3" Grid.Column="0" Margin="5,2,5,2">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding ScaleCapIsLocal}" Value="True">
<Setter Property="Background" Value="{StaticResource LocalValueBackgroundBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox x:Name="nbTareTol" Text="{Binding TareTol}" Grid.Row="3" Grid.Column="1" Margin="5,2,5,2">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding TareTolIsLocal}" Value="True">
<Setter Property="Background" Value="{StaticResource LocalValueBackgroundBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
除了索引,在视图模型的每个属性具有xxxIsLocal倒数属性,所以下面的部分模型对应以上面的例子:
string ScaleName { get; set; }
bool ScaleNameIsLocal { get; set; }
string ScaleCap { get; set; }
bool ScaleCapIsLocal { get; set; }
string TareTol { get; set; }
bool TarTolIsLocal { get; set; }
我已经使用该接口上的索引来获取IsLocal值各地播放,但INotifyPropertyChanged的实施挣扎(获取模式,以提高我ndexer值更改事件),除了更大的问题是如何使用基于目标控件上的内容或文本绑定路径的绑定而不是绑定结果的值创建单个样式。
我受到IDataErrorInfo模式的启发,并使用Validation.ErrorTemplate,它在表面看起来很简单,像这样一个简单的重复模式看起来像WPF应该能够处理的东西,没有太多问题。
我不知道多久我需要这个确切的模板,但它是一种模式,我敢肯定我想再次使用,其中每个属性有可能具有多个状态(不只是错误)并使用状态作为触发器应用不同的样式。
我已经编辑这个职位,因为我还没有完全找到我想要的东西,但多亏Nikkita我更近了一步:)
通过使用自定义的附加属性,我们可以直接在控件中声明绑定到标志字段,现在可以在全局样式字典中正确定义样式触发器。
视图模型并没有改变,但是从上面的XML现在simplifed:
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<Trigger Property="att:IsLocal.Value" Value="True">
<Setter Property="Background" Value="{StaticResource LocalValueBackgroundBrush}" />
</Trigger>
</Style.Triggers>
</Style>
<TextBox Text="{Binding ScaleName}" Margin="5,2,5,2" Grid.Row="1" Grid.Column="2" att:IsLocal.Value="{Binding ScaleNameIsLocal}"></TextBox>
<TextBox Text="{Binding ScaleCap}" Grid.Row="3" Grid.Column="0" Margin="5,2,5,2" att:IsLocal.Value="{Binding ScaleCapIsLocal}"></TextBox>
<TextBox Text="{Binding TareTol}" Grid.Row="3" Grid.Column="1" Margin="5,2,5,2" att:IsLocal.Value="{Binding TareTolIsLocal}"></TextBox>
我与当前的解决方案最大的问题是,我仍然需要编辑很多如果我想将这个(或另一个)接口模式应用于现有的应用程序,则可以使用现有的XAML。即使在目前的形式中,也有超过20个字段,所以这20个机会可能会导致绑定错误,或者意外跳过一个。
而不是使用这么多的国旗,你为什么不创建一个附加的广告载体像IsTextLocallyChanged文本框和创建一个单一的风格为所有textBoxes.Correct我,如果我错理解它。 –
这不会绕过标志,但它应该解决样式问题,这将简化XAML。然后,我可以绑定到View模型中的标志。问题是视图模型包含标志,所以我们仍然需要声明XAML。你已经把我放在了正确的方向,但是......我将研究如何对自定义附加属性进行全局绑定 –