C# WPF MVVM是否有替代IValueConverter的方法
我有几组可观察到的项目集合,它们在后台线程上定期更新(30到60秒)。这些集合通过视图上的ItemsControl显示。父项和控件中的项具有多个与每个项的状态关联的显示属性C# WPF MVVM是否有替代IValueConverter的方法,c#,wpf,mvvm,C#,Wpf,Mvvm,我有几组可观察到的项目集合,它们在后台线程上定期更新(30到60秒)。这些集合通过视图上的ItemsControl显示。父项和控件中的项具有多个与每个项的状态关联的显示属性 状态将决定文本旁边显示的形状以及该形状的笔划和填充颜色 状态将决定该项目文本的背景色和文本颜色 状态将确定项目中是否显示倒计时计时器(计时器与viewmodel没有连接) 状态可能决定父容器的边框颜色 我目前正在为每个属性的单个iValueConverter中执行此逻辑。它可以工作,但感觉很累赘,而且很分散。我几乎想以某种方
public ObservableCollection<PanelItem> PanelItems1
{
get { return panelItems1; }
set
{
panelItems1 = value;
base.OnPropertyChanged("PanelItems1");
}
}
公共可观察收集面板项目1
{
获取{return panelItems1;}
设置
{
panelItems1=值;
基于财产变更(“面板项目1”);
}
}
PanelItem是一个小的属性集合,包括:名称、值(状态)、描述。ItemsControl类似于以下内容:
<Border Grid.Row="0" Grid.Column="0"
BorderBrush="{Binding Path=PanelGroup1.HighestStatus, Converter={StaticResource ParentBorderColorConverter}}"
BorderThickness="3" Height="Auto" Width="Auto" Margin="0,0,2,0">
<StackPanel Grid.Column="0" Grid.Row="0">
<Label Grid.Row="0" Grid.Column="0" Content="First Group" Style="{StaticResource panelTitle}" />
<ItemsControl ItemsSource="{Binding Path=PanelItems1, Mode=TwoWay}"
ItemTemplate="{StaticResource PanelItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<!-- Here is the Data Template -->
<DataTemplate x:Key="PanelItemTemplate">
<Viewbox MaxHeight="20" HorizontalAlignment="Left" Cursor="Hand">
<WrapPanel>
<Path Margin="2,2,2,2" StrokeThickness="2">
<Path.Data>
<Binding Path="Status" Mode="OneWay" Converter="{StaticResource ShapeConverter}" />
</Path.Data>
<Path.Fill>
<Binding Path="Status" Mode="OneWay" Converter="{StaticResource ShapeColorConverter}" />
</Path.Fill>
<Path.Stroke>
<Binding Path="Status" Mode="OneWay" Converter="{StaticResource ShapeBorderConverter}" />
</Path.Stroke>
</Path>
<ContentPresenter Content="{Binding Path=Name}" Margin="5,0,0,0" />
</WrapPanel>
</Viewbox>
</DataTemplate>
</StackPanel>
</Border>
为什么不声明一个普通类来实现
状态对象的INotifyPropertyChanged
接口?只需在其中添加所需的属性,例如几何体
、填充
和笔划
等。。。如果您这样做了,就不需要任何转换器
类,您可以这样做:
<DataTemplate x:Key="PanelItemTemplate">
<Viewbox MaxHeight="20" HorizontalAlignment="Left" Cursor="Hand" >
<WrapPanel>
<Path Margin="2,2,2,2" StrokeThickness="2" >
<Path.Data>
<Binding Path="Status.Geometry" Mode="OneWay" />
</Path.Data>
<Path.Fill>
<Binding Path="Status.Fill" Mode="OneWay" />
</Path.Fill>
<Path.Stroke>
<Binding Path="Status.Stroke" Mode="OneWay" />
</Path.Stroke>
</Path>
<ContentPresenter Content="{Binding Path=Name}" Margin="5,0,0,0" />
</WrapPanel>
</Viewbox>
</DataTemplate>
可以只创建一个转换器,其中包含所有转换逻辑,并返回一个新类,您将绑定到该类:
public class MyNewConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Perform all required conversions here and return them as a new type of object
return new
{
Data = ...,
Fill = ...,
Stroke = ...
};
}
}
然后,您只需修改路径
的数据上下文
属性即可使用此转换器
<Viewbox MaxHeight="20" HorizontalAlignment="Left" Cursor="Hand">
<WrapPanel>
<Path Margin="2,2,2,2" StrokeThickness="2" DataContext="{Binding Path=Status, Converter={StaticResource MyNewConverter}}">
<Path.Data>
<Binding Path="Data" Mode="OneWay" />
</Path.Data>
<Path.Fill>
<Binding Path="Fill" Mode="OneWay" />
</Path.Fill>
<Path.Stroke>
<Binding Path="Stroke" Mode="OneWay" />
</Path.Stroke>
</Path>
<ContentPresenter Content="{Binding Path=Name}" Margin="5,0,0,0" />
</WrapPanel>
</Viewbox>
您是否考虑过使用可视状态管理器?您可以使用VSM滚动您自己的控件模板以备份任何可视状态-显然,它需要知道它绑定到什么,以便有条件地应用这些状态-您也可以使用触发器而不是值转换器,而不是公开单个状态并应用3个不同的转换器,你可以在你的虚拟机上公开3个不同的属性,并进行3次转换,以在虚拟机中(或在虚拟机调用的逻辑中)给它们一个值。检查这里,了解有关VSM的信息-还有关于触发器的相关信息-我总是将值转换器视为转换值的一种方式,不触发视觉状态,所以我尝试在任何麻烦的事情上避免它们,因为它们最终是代码而不是markup@Charleh我以前没见过这个,很有趣。我现在正在读。它看起来更多地用于UI交互事件,但我可能能够将其绑定到viewmodel上的属性。看起来我必须为每个控件添加一个VSM,然后根据视图切换视觉状态。@stijn当您说在VM上公开3个属性时,这些属性是颜色吗?如果是这样,它会将视图特定的显示知识放入ViewModel。请记住,像Fill
和Stroke
这样的属性表示视觉状态,如果您打算正确遵循MVVM模式,则不应成为ViewModel的一部分。“应该”并不意味着“必须”我喜欢这个想法,我可以创建一个包含该逻辑的类。我的问题是它适合哪里?视图的DataContext设置为my ViewModel,items控件绑定到该ViewModel上的一组项,如何在它们之间插入新的状态类?我同意Adi,Fill
和Stroke
不应该是VM的一部分,因为视图应该根据VM内容决定视觉状态。你可以打破这条规则,但是如果你把视图交给用户体验/用户界面设计师,而他们为了改变视觉状态而不得不与视图模型混为一谈,那就有点违背了MVVM的全部目的。使用触发器或VSM可以很容易地获取可视状态以对viewmodel属性作出反应。你可以对MVVM“半严格”,但如果你能找到一种不“作弊”的方法,那么你就是在学习,通常是在创建一个更健壮的解决方案。然而,反过来说,如果你的VM是特定于应用程序的,并且包装了一个特定的数据项,那么你可能会认为它与视图密切相关。如果您正在重用viewmodels,那么很可能是错误的方法我非常喜欢这个想法!我刚才遇到的唯一障碍是一些额外的要求,需要在某些状态下闪烁背景色(可能是故事板?)和声音通知。我不知道该怎么开始