问题描述
我有一个DataGrid,其中显示了一些详细信息的地图列表。我正在尝试更改当前处于活动状态的地图的前景色,但是我正在努力。我已经编写了以下转换器,以检查DataGrid项的值是否与当前地图的名称匹配,但是我不确定如何从XAML传递当前地图的名称。
转换器:
public class StringToBrushConverter : IValueConverter
{
public string CurrentMapName { get; set; }
public Color CurrentMapColor { get; set; }
public Color OtherMapColor { get; set; }
string _value = "";
public StringToBrushConverter(string currentMapName,Color currentMapColor,Color otherMapColor)
{
CurrentMapName = currentMapName;
CurrentMapColor = currentMapColor;
OtherMapColor = otherMapColor;
}
public object Convert(object value,Type targettype,object parameter,CultureInfo culture)
{
_value = value as string;
return (string)value == CurrentMapName ? new SolidColorBrush(CurrentMapColor) : new SolidColorBrush(OtherMapColor);
}
public object ConvertBack(object value,CultureInfo culture)
{
return _value; //Todo: Will this work?
}
}
public sealed class RaceMapColorConverter : StringToBrushConverter
{
public RaceMapColorConverter() : base("",new Color { R = 255,G = 0,B = 0 },G = 255,B = 255 }) { }
}
XAML:
<DataGrid x:Name="MapHistory"
AutoGenerateColumns="False"
IsReadOnly="True"
HeadersVisibility="Column"
GridLinesVisibility="None"
CanUserSortColumns="False"
Style="{StaticResource MapTimerDataGrid}"
CellStyle="{StaticResource MapTimerControlCell}"
ItemsSource="{Binding Plan.Plan}">
<DataGrid.Resources>
<!-- The Binding in CurrentMapName is not valid. It says it can only be set on a dependency property but I'm not sure how to do that -->
<conv:RaceMapColorConverter x:Key="MapColorConverter" CurrentMapName="{Binding CurrentMap.MapName}" CurrentMapColor="Red" OtherMapColor="White" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Map" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Map.MapName}" Foreground="{Binding Map.MapName,Converter={StaticResource MapColorConverter}}" Padding="0" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Other columns removed to shorten -->
</DataGrid.Columns>
</DataGrid>
我也不确定如何实现'ConvertBack()`。将原始值存储在转换器中会起作用吗?还是可以为同一控件创建一个新实例?我什至会以正确的方式这样做吗?我以为还值得一提的是,我正在使用Caliburn.Micro,以防万一它有任何技巧可以帮助您。任何帮助将不胜感激。
解决方法
作为一般的经验法则,当数据转换需要双向时(即,视图模型可以再次查看和返回),应使用转换器,而仅单向时应使用DataTriggers。这就回答了您有关ConvertBack的问题(在您提供的示例中,无论如何都不会调用它,在这种情况下,您可以只返回Binding.DoNothing)。
但是,在这种特殊情况下,必须使用转换器,因为您需要比较两个绑定。与其为这个非常具体的任务编写一个应用程序感知的转换器,不如选择一个更通用的MultiConverter,它只比较您提供的两个值:
public class EqualityConverter : IMultiValueConverter
{
public object Convert(object[] values,Type targetType,object parameter,CultureInfo culture)
{
return (values.Length==2) && Object.Equals(values[0],values[1]);
}
public object[] ConvertBack(object value,Type[] targetTypes,CultureInfo culture)
{
return new object[] { Binding.DoNothing,Binding.DoNothing };
}
}
然后在您的应用程序中,将两个绑定都传递到这种类型的MultiBinding中,并在比较结果为true时使用DataTrigger更改地图颜色:
<Label Content="{Binding Map.MapName}">
<Label.Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="Foreground" Value="Red" /> <!-- normal map color -->
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource EqualityConverter}" Mode="OneWay">
<Binding Path="Map.MapName" />
<Binding Path="CurrentMapName" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="White" /> <!-- other map color -->
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>