WPF DataGridColumnHeader 模板中简单 math-styling 的数据 binding/conversion
Data binding/conversion for simple math-styling in a WPF DataGridColumnHeader template
我的目标是将类似 "A__B" 的格式字符串传递给 DataGrid 列的 header 并将其显示为
A 带有下标 B(即 )。要在 per-column 基础上执行此操作,我打算使用如下模板。
<DataGridTextColumn Binding="{Binding AB}", Header="A__B" HeaderStyle="{StaticResource ColumnHeaderTemplate}" />
为了实现合适的模板,我想我可能需要使用转换器。因此,我写了
一个简单的转换器,将字符串拆分为 object 的 class 符号,具有文本和下标属性。
using System;
using System.Windows.Data;
using System.Globalization;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Test
{
public class Symbol : INotifyPropertyChanged
{
string text_, subscript_;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public Symbol(string text, string subscript)
{
Text = text;
Subscript = subscript;
NotifyPropertyChanged();
}
public String Text
{
get { return text_; }
set { text_ = value; NotifyPropertyChanged(); }
}
public String Subscript
{
get { return subscript_; }
set { subscript_ = value; NotifyPropertyChanged(); }
}
}
[ValueConversion(typeof(string), typeof(Symbol))]
public class StringToSymbolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null) return null;
var format = parameter as string;
int idx = format.IndexOf("__");
if (idx < 0) return new Symbol(format, "");
return new Symbol(format.Substring(0, idx), format.Substring(idx + 2);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}
我将此转换器添加到 window 资源
<Window.Resources>
<l:StringToSymbolConverter x:Key="stringToSymbolConverter" />
</Window.Resources>
在我的数据网格中,我做了以下操作
<DataGrid x:Name="dataGrid" ItemsSource="{Binding Results}" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}" x:Key="ColumnHeaderTemplate">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" DataContext="{Binding Converter={StaticResource stringToSymbolConverter}}">
<Run Text="{Binding Path=Text}"/>
<Run Text="{Binding Path=Subscript}" BaselineAlignment="Subscript" FontSize="8"/>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding AB, Mode=OneWay}" ClipboardContentBinding="{x:Null}" Header="A__B" HeaderStyle="{StaticResource ColumnHeaderTemplate}" />
</DataGrid.Columns>
</DataGrid>
我的想法是转换一次
然后将驻留在 Symbol object 中的组件插入正确的位置。为此,我尝试(错误?)使用文本块的 DataContext。
现在这没有按预期工作,我没有看到任何输出。我看到模板正在应用于相应的列,所以我似乎有一个正确的。此外,如果我用纯文本替换绑定或添加回退值,则文本会正确呈现。我怀疑绑定失败并在运行时传递一个空字符串。作为 WPF 的新手,鉴于 XAML/WPF 中的调试工具链相当有限,我很难找出问题所在以及从这里去哪里。
我可能完全错误地理解了绑定游戏中涉及的依赖关系,这可能是由于我缺乏对底层机制的理解,尤其是在涉及模板时。因此,我感谢任何有用的提示!
有什么想法吗?
错误出在您的转换器中 - 也就是说,您试图转换参数 null
而不是值,因为您没有为绑定指定 ConverterParameter
使用转换器的地方。因此,您得到一个空列 header。您应该改为转换该值:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//here you should use 'value' instead of 'parameter'
if (value == null) return null;
var format = value as string;
int idx = format.IndexOf("__");
if (idx < 0) return new Symbol(format, "");
return new Symbol(format.Substring(0, idx), format.Substring(idx + 2);
}
请注意,这种错误很容易调试 - 每当您遇到涉及转换器的绑定问题时,在 Convert
方法中设置断点并逐步执行它是有益的。
我的目标是将类似 "A__B" 的格式字符串传递给 DataGrid 列的 header 并将其显示为 A 带有下标 B(即 )。要在 per-column 基础上执行此操作,我打算使用如下模板。
<DataGridTextColumn Binding="{Binding AB}", Header="A__B" HeaderStyle="{StaticResource ColumnHeaderTemplate}" />
为了实现合适的模板,我想我可能需要使用转换器。因此,我写了 一个简单的转换器,将字符串拆分为 object 的 class 符号,具有文本和下标属性。
using System;
using System.Windows.Data;
using System.Globalization;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Test
{
public class Symbol : INotifyPropertyChanged
{
string text_, subscript_;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public Symbol(string text, string subscript)
{
Text = text;
Subscript = subscript;
NotifyPropertyChanged();
}
public String Text
{
get { return text_; }
set { text_ = value; NotifyPropertyChanged(); }
}
public String Subscript
{
get { return subscript_; }
set { subscript_ = value; NotifyPropertyChanged(); }
}
}
[ValueConversion(typeof(string), typeof(Symbol))]
public class StringToSymbolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null) return null;
var format = parameter as string;
int idx = format.IndexOf("__");
if (idx < 0) return new Symbol(format, "");
return new Symbol(format.Substring(0, idx), format.Substring(idx + 2);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}
我将此转换器添加到 window 资源
<Window.Resources>
<l:StringToSymbolConverter x:Key="stringToSymbolConverter" />
</Window.Resources>
在我的数据网格中,我做了以下操作
<DataGrid x:Name="dataGrid" ItemsSource="{Binding Results}" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}" x:Key="ColumnHeaderTemplate">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" DataContext="{Binding Converter={StaticResource stringToSymbolConverter}}">
<Run Text="{Binding Path=Text}"/>
<Run Text="{Binding Path=Subscript}" BaselineAlignment="Subscript" FontSize="8"/>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding AB, Mode=OneWay}" ClipboardContentBinding="{x:Null}" Header="A__B" HeaderStyle="{StaticResource ColumnHeaderTemplate}" />
</DataGrid.Columns>
</DataGrid>
我的想法是转换一次 然后将驻留在 Symbol object 中的组件插入正确的位置。为此,我尝试(错误?)使用文本块的 DataContext。
现在这没有按预期工作,我没有看到任何输出。我看到模板正在应用于相应的列,所以我似乎有一个正确的。此外,如果我用纯文本替换绑定或添加回退值,则文本会正确呈现。我怀疑绑定失败并在运行时传递一个空字符串。作为 WPF 的新手,鉴于 XAML/WPF 中的调试工具链相当有限,我很难找出问题所在以及从这里去哪里。
我可能完全错误地理解了绑定游戏中涉及的依赖关系,这可能是由于我缺乏对底层机制的理解,尤其是在涉及模板时。因此,我感谢任何有用的提示!
有什么想法吗?
错误出在您的转换器中 - 也就是说,您试图转换参数 null
而不是值,因为您没有为绑定指定 ConverterParameter
使用转换器的地方。因此,您得到一个空列 header。您应该改为转换该值:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//here you should use 'value' instead of 'parameter'
if (value == null) return null;
var format = value as string;
int idx = format.IndexOf("__");
if (idx < 0) return new Symbol(format, "");
return new Symbol(format.Substring(0, idx), format.Substring(idx + 2);
}
请注意,这种错误很容易调试 - 每当您遇到涉及转换器的绑定问题时,在 Convert
方法中设置断点并逐步执行它是有益的。