我的目标是将格式化的字符串传递到datatemplate中:
<ContentControl ContentTemplate="{StaticResource WorkingLabelTemplate}" Content="123"
ContentStringFormat="Number is {0}" Grid.Row="0"/>
<ContentControl ContentTemplate="{StaticResource NotWorkingLabelTemplate}" Content="123"
ContentStringFormat="Number is {0}" Grid.Row="1"/>
第一种方法:
<DataTemplate x:Key="WorkingLabelTemplate">
<Label Content="{Binding}"
ContentStringFormat="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=ContentStringFormat, Converter={StaticResource TestConverter}}"/>
</DataTemplate>
第二种方法:
<DataTemplate x:Key="NotWorkingLabelTemplate">
<Label Content="{Binding}"
ContentStringFormat="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContentControl},
Path=ContentStringFormat, Converter={StaticResource TestConverter}}"/>
</DataTemplate>
对于这两种方法,TestConverter均表示绑定正常工作:
TestConverter:“编号为{0}”,类型为“ System.String”到“ System.String”,参数“ TestConverter:类型'System.String'到'System.String'的'数字为{0}',参数”
但是第二种方法不起作用: screenshot
问题: 为什么第二种方法不起作用,而绑定结果却相同?
答案 0 :(得分:2)
TL; DR
我使用了您的项目,发现在我的计算机上安装的所有.Net框架中都发生了同样的事情。因此,我挖了更多的北斗星以了解发生了什么,我得出的结论是,这只是一个定时问题,您的工作模板的ContentStringFormat
属性正在评估中(而不是绘制标签之前)。
解决方案
要解决您的问题,请从以下位置更改构造函数代码:
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
收件人:
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
如果您想阅读一些真正有趣的东西,请继续阅读!
为什么我认为这是时间问题?
我在两个模板diag:PresentationTraceSources.TraceLevel=High
上都设置了诊断属性,并在日志后找到了
如果仔细观察这两张图片,您会发现评估ContentStringFormat
属性所花费的时间之间存在时间差异。
另一种证明
我对您的项目进行了另一项更改,这证明了我的信念是正确的。如果您在下面运行代码,则该代码类似于您的项目,但有两个附加按钮;一个更改数据,另一个更改字符串格式。当您运行程序并更改字符串格式时,内容不会以新的字符串格式重新呈现,但是当您自行更改数据时,它会重新评估字符串格式并重新呈现控件!
MainWindow.xaml
<Window x:Class="StringFormatTestProject.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:StringFormatTestProject"
mc:Ignorable="d"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:TestConverter x:Key="TestConverter"/>
<DataTemplate x:Key="WorkingLabelTemplate">
<Label Content="{Binding diag:PresentationTraceSources.TraceLevel=High}"
ContentStringFormat="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=ContentStringFormat, Converter={StaticResource TestConverter}, diag:PresentationTraceSources.TraceLevel=High}"/>
</DataTemplate>
<DataTemplate x:Key="NotWorkingLabelTemplate">
<Label Content="{Binding}"
ContentStringFormat="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContentControl},
Path=ContentStringFormat, Converter={StaticResource TestConverter}}">
</Label>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ContentControl ContentTemplate="{StaticResource NotWorkingLabelTemplate}" Content="{Binding SomeDatatInVM}"
ContentStringFormat="{Binding FormatStringInVM}" Grid.Row="0"/>
<ContentControl ContentTemplate="{StaticResource WorkingLabelTemplate}" Content="{Binding SomeDatatInVM}"
ContentStringFormat="{Binding FormatStringInVM}" Grid.Row="1"/>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Click="Button_Click" Grid.Column="0">Change Data</Button>
<Button Click="Button_Click_1" Grid.Column="2">Change Format String</Button>
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string formatStringInVM = "Peer: {0}";
public string FormatStringInVM
{
get { return formatStringInVM; }
set
{
formatStringInVM = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FormatStringInVM)));
}
}
private int someDatatInVM = 123;
public int SomeDatatInVM
{
get { return someDatatInVM; }
set
{
someDatatInVM = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SomeDatatInVM)));
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
private void Button_Click(Object sender, RoutedEventArgs e)
{
SomeDatatInVM++;
}
private static int i = 1;
private void Button_Click_1(Object sender, RoutedEventArgs e)
{
FormatStringInVM = "Peer-" + i.ToString() + ": {0}";
i++;
}
}