【问题标题】:How to use Static Resource for WPF datagrid comboBox binding如何将静态资源用于 WPF 数据网格组合框绑定
【发布时间】:2019-09-04 07:26:55
【问题描述】:

我也在开发带有实体框架的 WPF 应用程序。 但我不使用 MVVM 我有一个 ENUM 类型,所以我需要使用所有枚举类型初始化组合框项目源并根据我的数据选择值。为了简化,只需考虑将简单列表绑定到组合框。我已经厌倦了不同的方式,但有一个我无法弄清楚的问题。

<Page x:Class="Library.View.Reader"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:Library.View"
  mc:Ignorable="d" 
  d:DesignHeight="300"
  Title="Reader" Width="900">


<Grid Margin="0,0,0,0">

    <DataGrid Name="grid_reader"    AutoGenerateColumns="True" HorizontalAlignment="Left" Height="126" Margin="23,20,0,0" VerticalAlignment="Top" Width="845" RowEditEnding="grid_reader_RowEditEnding" AutoGeneratingColumn="grid_reader_AutoGeneratingColumn">
        <DataGrid.Columns>

               <DataGridComboBoxColumn Header="Type"
                ItemsSource="{DynamicResource enumlist}}"
                DisplayMemberPath="Name"
                SelectedValuePath="Id"
                SelectedValueBinding="{Binding Type}"
        </DataGrid.Columns>
    </DataGrid>

</Grid>

我已经尝试过 DynamicResource、StaticResource、Binding。它们都不起作用!

  public partial class Reader : Page
  {
  public Reader() // Redaer is my page in xaml
    { 
        LibraryDataAccess.Model1 model = new Model1();
        List<LibraryDataAccess.Model.Reader> list = new List<LibraryDataAccess.Model.Reader>();
        list = model.Readers.ToList();
    public ObservableCollection<ReaderType> enumlist { get; set; }
 // initialize datagrid succefully Also enumlist = getEnumValues();
        enumlist = new ObservableCollection<ReaderType>();
        //enumlist = new List<LibraryDataAccess.EnumTypes.ReaderType>();
        typelist = Enum.GetValues(typeof      
        (LibraryDataAccess.EnumTypes.ReaderType))
        .Cast<LibraryDataAccess.EnumTypes.ReaderType>().Select(x => new ReaderType { Id = (int)x, Name = x.ToString() }).ToList();
        foreach (var item in typelist)
        {

            enumlist.Add(item);
        }
    grid_reader.ItemsSource = list;
    }

    public class ReaderType
    {
    public  int Id { get; set; }
    public   string Name { get; set; }
    }
 }

Combo 中没有加载任何内容。解决办法是什么。谢谢

已编辑

我 99% 确定问题出在组合 BUT 的 ItemSource 上

我需要用枚举值填充的组合,并且选定的值显示为给定的值,如 Staff(在 id 为 2 的枚举列表中),无论如何组合都不会被填充。我在单独的 wpf 页面中使用它。

我认为问题出在与组合框相关的数据上下文中,我什至尝试使用分离的组合框,使用上面提到的绑定,但它不起作用。

当我使用 AUTOGENERATED = true 时,组合框会很好地创建并带有选择值。

【问题讨论】:

  • 您想将枚举列表绑定到组合框吗?那么你能用你的枚举列表定义来展示你所有的编码吗
  • 请查看已编辑和已编辑的代码,非常感谢
  • 什么是grid_reader,你的datagrid的名字?
  • 是的,它是数据网格
  • 只有一段代码很难理解..请用datagrid的定义显示你的xaml代码

标签: c# wpf combobox binding datagrid


【解决方案1】:

如果我知道你想要什么(否则我会破坏答案):这是一个使用枚举列表的组合框的数据网格的解决方案:我正在为此使用标记扩展

你的 class.cs:如果你想更新数据,我已经实现了 INotifyPropertyChanged

using System.ComponentModel;

namespace zzWpfApp1
{
    [TypeConverter(typeof(EnumDescriptionTypeConverter))]
    public enum ReaderType
    {
        [Description("Super Chief")] Chief,
        [Description("Super Staff")] Staff,
        [Description("super Officer")] Officer,
    }
    public class User : INotifyPropertyChanged
    {
        private string _name;
        private ReaderType _readerType;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }

        public ReaderType ReaderType
        {
            get { return _readerType; }
            set
            {
                _readerType = value;
                NotifyPropertyChanged("ReaderType");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

EnumConverter.cs: 用于捕获枚举文件描述的通用文件

using System;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Markup;

namespace zzWpfApp1
{
    public class EnumBindingSourceExtension : MarkupExtension
    {
        private Type _enumType;

        public Type EnumType
        {
            get { return this._enumType; }
            set
            {
                if (value != this._enumType)
                {
                    if (null != value)
                    {
                        Type enumType = Nullable.GetUnderlyingType(value) ?? value;

                        if (!enumType.IsEnum)
                            throw new ArgumentException("Type must be for an Enum.");
                    }

                    this._enumType = value;
                }
            }
        }

        public EnumBindingSourceExtension(Type enumType)
        {
            this.EnumType = enumType;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (null == this._enumType)
                throw new InvalidOperationException("The EnumType must be specified.");

            Type actualEnumType = Nullable.GetUnderlyingType(this._enumType) ?? this._enumType;
            Array enumValues = Enum.GetValues(actualEnumType);

            if (actualEnumType == this._enumType)
                return enumValues;

            Array tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1);
            enumValues.CopyTo(tempArray, 1);
            return tempArray;
        }
    }
    public class EnumDescriptionTypeConverter : EnumConverter
    {
        public EnumDescriptionTypeConverter(Type type)
            : base(type)
        {
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture,
            object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                if (value != null)
                {
                    FieldInfo fi = value.GetType().GetField(value.ToString());
                    if (fi != null)
                    {
                        var attributes =
                            (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
                        return ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description)))
                            ? attributes[0].Description
                            : value.ToString();
                    }
                }
                return string.Empty;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
}
---

mainwindow.xaml.cs:

namespace zzWpfApp1
{
    public partial class MainWindow : Window
    {
        public ObservableCollection<User> Users { get; set; }
        public MainWindow()
        {
            //Sample of different users
            List<User> users = new List<User>();
            users.Add(new User() { Name = "Donald Duck", ReaderType = ReaderType.Chief });
            users.Add(new User() { Name = "Mimmi Mouse", ReaderType = ReaderType.Staff });
            users.Add(new User() { Name = "Goofy", ReaderType = ReaderType.Officer });
            Users = new ObservableCollection<User>(users);

            InitializeComponent();
            DataContext = this;
        }
     }
} 

xaml 文件:

       <DataGrid Name="grid_reader" AutoGenerateColumns="False" Margin="20,20,300,20" ItemsSource="{Binding Users}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
                <DataGridComboBoxColumn Header="ReaderType"  MinWidth="150" 
                                        SelectedItemBinding="{Binding ReaderType}"
                                        ItemsSource="{Binding Source={local:EnumBindingSource {x:Type local:ReaderType}}}"/>
            </DataGrid.Columns>     

【讨论】:

  • 这不是 MVVM 吗?我宁愿不为这个项目使用 MVVM。顺便说一句,非常感谢您的回复。
【解决方案2】:

终于为我的问题找到了一个更好更简单的答案,和大家分享一下:

我们需要定义一个类作为组合框的数据源。所以所有的组合框都必须有这些数据,然后根据我们设置的属性(来自数据网格数据源)必须选择并显示组合框值。我们还需要在页面或窗口的顶部定义一个组合框资源。

    <Page.Resources>
        <local:viewmodel x:Key="viewmodel"/>
    </Page.Resources>


    <Grid Margin="0,0,0,0">

    <DataGrid Name="grid_doc" AutoGenerateColumns="True" HorizontalAlignment="Left" Height="100" Margin="31,55,0,0" VerticalAlignment="Top" Width="636">
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="PublisherId"
                ItemsSource="{StaticResource viewmodel}"
                              SelectedValueBinding="{Binding PublisherId , UpdateSourceTrigger=PropertyChanged}"
                              DisplayMemberPath="Value" 
                              SelectedValuePath="Key">
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
    <ComboBox HorizontalAlignment="Left" Margin="130,193,0,0" VerticalAlignment="Top" Width="120"
        ItemsSource="{StaticResource viewmodel}"
                              SelectedValue="{Binding PublisherId , UpdateSourceTrigger=PropertyChanged}"
                              DisplayMemberPath="Value" 
                              SelectedValuePath="Key">
    </ComboBox>

</Grid>

注意这里,我对选定和显示成员使用了 Key 和 Value。它很重要,甚至 key 和 value 都是错误的。它必须是 ValueKey,并带有 大写。 我发布了一个更简单的版本,不是枚举成员,它没有任何区别。您可以创建枚举成员列表,然后将其添加到您的视图模型类中。您的视图模型类是否具有其他属性并不重要。只要确保返回一个 Enumerable 数据或从上层 Enumerable 类继承,就像我做的那样。

 public partial class Document : Page
{

    LibraryDataAccess.Model1 model;

    List<LibraryDataAccess.Model.Document> list;
    public Document()
    {
        model = new Model1();
        list = new List<LibraryDataAccess.Model.Document>();
        list = model.Documents.ToList();
        InitializeComponent();
        list.Add(new LibraryDataAccess.Model.Document { Id = 1, PublisherId = 2, Title = "sdfs" });
        grid_doc.ItemsSource = list;

    }

    public class viewmodel : List<KeyValuePair<string,string>>
    {

    public viewmodel()
    {

        this.Add(new KeyValuePair<string, string>(1.ToString(), "s"));
        this.Add(new KeyValuePair<string, string>(2.ToString(), "t"));
    }
    }

感谢之前的回答和这两个对我有帮助的链接:

binding

static resource

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 2014-01-08
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多