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

标签 c# wpf listbox itemtemplate

我将这个问题命名为第二部分,因为我已经在这里提出了一个类似但更简单的关于在 WPF 中为 ListBox 创建 ItemTemplat 的问题 Create ItemTemplate for ListBox in code-beind in WPF

现在我要扩展我的问题。我想要一个 ListBox 的 ItemTemplate,以便可以在绑定(bind)或不绑定(bind)到 ObservableCollection 的情况下使用它。

如果我不想将 ItemsSource 绑定(bind)到 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 绑定(bind)到 ObservableCollection,因为 TextBlock.TextProperty 必须绑定(bind)到 DisplayMemberPath 属性。

抱歉语法错误。

最佳答案

首先,您需要创建一个变量来确定状态:正在使用集合,或者只是字符串数组。该标志也可以是依赖属性,在我的示例中它是一个 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>

代码隐藏

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

关于c# - 在 WPF 的代码隐藏中为 ListBox 创建 ItemTemplate - 第 II 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23081311/

相关文章:

wpf - 在 WPF 网格/列表中跨越多列的最佳方法?

c# - 如何在Azure Function C#中获取文件夹路径

c# - 在类中为属性赋值

wpf - 如何在 WPF 数据网格中选择单个单元格?

wpf - 在列表框中加入分隔符

wpf - ListBoxItem IsSelected 样式

c# - 查找具有条件的所有可能二进制组合的算法

c# - JSON.NET 序列化 JObject 而忽略空属性

wpf - Loaded 之后和显示用户控件之前是否有任何事件?

c# - WPF:具有多个数据模板的 TabControl