在WPF-第二部分的代码隐藏中为ListBox创建ItemTemplate

本文关键字:ListBox 创建 ItemTemplate 隐藏 WPF- 第二部分 代码 | 更新日期: 2023-09-27 17:58:34

我把我的这个问题命名为第二部分,因为我已经在这里问了一个类似但更简单的问题,关于在WPF 中的代码中为ListBox创建ItemTemplate

现在我要扩大我的问题。我想要一个ListBox的ItemTemplate,这样它就可以在绑定或不绑定ObservableCollection的情况下使用。

如果我不想将ItemsSource绑定到ObservableCollection,我会使用以下代码:

var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
textBlockFactory.SetValue(TextBlock.TextProperty, new Binding(".")); // Here
textBlockFactory.SetValue(TextBlock.BackgroundProperty, Brushes.Red);
textBlockFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Wheat);
textBlockFactory.SetValue(TextBlock.FontSizeProperty, 18.0);
var template = new DataTemplate();            
template.VisualTree = textBlockFactory;
MyListBox.ItemTemplate = template;

但是它不适用于ItemsSource绑定到ObservableCollection,因为TextBlock.TextProperty必须绑定到DisplayMemberPath属性。

抱歉语法不好。

在WPF-第二部分的代码隐藏中为ListBox创建ItemTemplate

首先,您需要创建一个变量来确定状态:正在使用一个集合,或者只是一个字符串数组。这个标志也可以是一个依赖属性,在我的例子中,它是一个SomeFlag:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    bool SomeFlag = false;
    if (SomeFlag == false)
    {
        var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
        textBlockFactory.SetValue(TextBlock.TextProperty, new Binding("."));
        textBlockFactory.SetValue(TextBlock.BackgroundProperty, Brushes.Red);
        textBlockFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Wheat);
        textBlockFactory.SetValue(TextBlock.FontSizeProperty, 18.0);
        var template = new DataTemplate();
        template.VisualTree = textBlockFactory;
        MyListBox.ItemTemplate = template;
    }
    else
    {
        MyListBox.DisplayMemberPath = "Name";
        MyListBox.SelectedValuePath = "Age";
    }
}

为了测试,添加SelectionChanged事件的处理程序:

private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine("SelectedValue is " + MyListBox.SelectedValue);
}

下面是一个完整的例子:

XAML

<Grid>
    <ListBox Name="MyListBox"
             SelectionChanged="MyListBox_SelectionChanged"
             ItemsSource="{Binding Path=MyCollection}" />
</Grid>

Code-behind

public partial class MainWindow : Window
{
    ViewModel MyViewModel = new ViewModel();
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = MyViewModel;
        MyViewModel.MyCollection = new ObservableCollection<Person>();
        MyViewModel.MyCollection.Add(new Person()
        {
            Age = 22,
            Name = "Nick",
        });
        MyViewModel.MyCollection.Add(new Person()
        {
            Age = 11,
            Name = "Sam",
        });
        MyViewModel.MyCollection.Add(new Person()
        {
            Name = "Kate",
            Age = 15,
        });
    }
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        bool SomeFlag = false;
        if (SomeFlag == false)
        {
            var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
            textBlockFactory.SetValue(TextBlock.TextProperty, new Binding("."));
            textBlockFactory.SetValue(TextBlock.BackgroundProperty, Brushes.Red);
            textBlockFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Wheat);
            textBlockFactory.SetValue(TextBlock.FontSizeProperty, 18.0);
            var template = new DataTemplate();
            template.VisualTree = textBlockFactory;
            MyListBox.ItemTemplate = template;
        }
        else
        {
            MyListBox.DisplayMemberPath = "Name";
            MyListBox.SelectedValuePath = "Age";
        }
    }
    private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("SelectedValue is " + MyListBox.SelectedValue);
    }
}
public class ViewModel : NotificationObject
{
    #region MyCollection
    public ObservableCollection<Person> MyCollection
    {
        get;
        set;
    }
    #endregion
}
#region Model
public class Person
{
    public string Name
    {
        get;
        set;
    }
    public int Age
    {
        get;
        set;
    }
}
#endregion
#region NotificationObject
public class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
#endregion