如何将静态资源用于WPF数据网格comboBox绑定

时间:2019-04-13 21:43:27

标签: c# wpf combobox binding datagrid

我也在开发带有实体框架的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; }
    }
 }

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

已编辑

我99%确信问题是组合BUT的ItemSource

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

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

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

2 个答案:

答案 0 :(得分:0)

如果我不确定您想要什么(否则我将破坏答案):这是使用带有enumlist的combobox的datagrid解决方案:我为此使用了markupextension

您的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>     

答案 1 :(得分:0)

Finally I found a better and simpler answer for my question, let me share with you guys:

We need to define a class as the dataSource of our combo box. So all of combo boxes must have these datas, and then based on a property which we set(from the data grids data source) combo box value must be selected and shown. Also we need to define a combo box resource at the top of the page, or window.

    <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>

NOTE here, I used Key and Value for selected and display members. its important, even key and value are wrong. it MUST be Value and Key, with uppercase. I posted a simpler version, not enum members, it does not make any difference. you can create your list of enum members, and then add it into in your viewmodel class.It doesn't matter if your viewmodel class has other properties. just be sure to return an Enumerable data or inherit from a upper Enumerable class, as I did.

 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"));
    }
    }

Thanks to previous answer and to these two links which helped me :

binding

static resource