在WPF中如何更改代码中的DataTemplate的文本块的文本绑定?
我有一个ListBox的ItemsSource绑定到一个对象列表。 Listbox有一个带有包含TextBlock的DataTemplate的ItemTemplate。 文本块的文本被绑定到对象的Name属性(即Text =“{Binding Name}”)。
我想提供一个单选按钮来显示同一列表的不同视图。 例如,允许用户在Name属性和ID属性之间切换。
我在2381740找到了这个答案,但我也在数据模板中设置了边框和文本框样式(请参阅下面的代码)。
无论如何只是重置文本块绑定? 我不想重新创建整个数据模板。 其实我甚至不知道如何做到这一点,是否有一种简单的方法来将xaml翻译成代码?
谢谢科迪
<DataTemplate>
<Border Margin="0 0 2 2"
BorderBrush="Black"
BorderThickness="3"
CornerRadius="4"
Padding="3">
<TextBlock Style="{StaticResource listBoxItemStyle}"
Text="{Binding Name}" />
</Border>
</DataTemplate>
只要简单一点,使用两个文本块并隐藏其中一个。
XAML:
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<StackPanel>
<RadioButton Name="nameRadioBtn" Content="Name" IsChecked="True"/>
<RadioButton Name="lengthRadioBtn" Content="Length" />
<ListBox
ItemsSource="{Binding Path=Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1">
<Grid>
<TextBlock
Text="{Binding .}"
Visibility="{Binding Path=IsChecked, ElementName=nameRadioBtn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBlock
Text="{Binding Path=Length}"
Visibility="{Binding Path=IsChecked, ElementName=lengthRadioBtn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
代码背后:
using System.Collections.Generic;
using System.Windows;
namespace Test
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = this;
}
public IEnumerable<string> Items
{
get
{
return new List<string>() {"Bob", "Sally", "Anna"};
}
}
}
}
Wallstreet程序员的解决方案适合您,因为您使用单选按钮。 然而,我认为我应该为未来的这个问题的读者提一个更一般的解决方案。
你可以改变你的DataTemplate使用普通的“{Binding}”
<DataTemplate x:Key="ItemDisplayTemplate">
<Border ...>
<TextBlock ...
Text="{Binding}" />
</Border>
</DataTemplate>
然后在代码中,您不必重新创建完整的DataTemplate。 你所要做的就是重新创建这个:
<DataTemplate>
<ContentPresenter Content="{Binding Name}" ContentTemplate="{StaticResource ItemDisplayTemplate}" />
</DataTemplate>
这很简单:
private DataTemplate GeneratePropertyBoundTemplate(string property, string templateKey)
{
var template = FindResource(templateKey);
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(ContentPresenter));
factory.SetValue(ContentPresenter.ContentTemplateProperty, template);
factory.SetBinding(ContentPresenter.ContentProperty, new Binding(property));
return new DataTemplate { VisualTree = factory };
}
如果您有很多属性,即使在您的单选按钮示例中,这也特别方便。
您也可以使用值转换器来挑选数据对象的任何属性。 您将需要绑定到整个对象而不是单个属性。 如果你的数据对象实现INotifyPropertyChanged,那么这个解决方案将不适合你。
XAML
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Test="clr-namespace:Test"
Height="300" Width="300">
<Window.Resources>
<Test:PropertyPickerConverter x:Key="PropertyPickerConverter" />
</Window.Resources>
<StackPanel>
<RadioButton Content="Name" Click="OnRadioButtonClick" IsChecked="True"/>
<RadioButton Content="Length" Click="OnRadioButtonClick" />
<ListBox
ItemsSource="{Binding Path=Items}"
Name="_listBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1">
<StackPanel>
<TextBlock
Text="{Binding ., Converter={StaticResource PropertyPickerConverter}}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
后面的代码:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace Test
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
_propertyPickerConverter = FindResource("PropertyPickerConverter") as PropertyPickerConverter;
_propertyPickerConverter.PropertyName = "Name";
DataContext = this;
}
public IEnumerable<string> Items
{
get
{
return new List<string>() {"Bob", "Sally", "Anna"};
}
}
private void OnRadioButtonClick(object sender, RoutedEventArgs e)
{
_propertyPickerConverter.PropertyName = (sender as RadioButton).Content as string;
_listBox.Items.Refresh();
}
private PropertyPickerConverter _propertyPickerConverter;
}
public class PropertyPickerConverter : IValueConverter
{
public string PropertyName { get; set; }
#region IValueConverter Members
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string item = value as string;
switch (PropertyName)
{
case "Name": return item;
case "Length": return item.Length;
default: return null;
}
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
#endregion
}
}
链接地址: http://www.djcxy.com/p/44593.html
上一篇: In WPF how to change a DataTemplate's Textblock's text binding in code?