Как использовать статический ресурс для привязки comboBox таблицы данных WPF - PullRequest
0 голосов
/ 14 апреля 2019

Я также занимаюсь разработкой приложения WPF с платформой управления данными. Но я НЕ пользуюсь MVVM У меня есть типы ENUM, поэтому мне нужно инициализировать источник элемента поля со списком ВСЕМИ типами 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. Каково решение. Спасибо

EDITED

Я на 99% уверен, что проблема в ItemSource комбо, НО :

Мне нужно комбо, заполненное значениями перечисления, и выбранное значение отображается как заданное, например, как Staff (который находится в списке перечисления с идентификатором 2), в любом случае комбо не будет заполнено вообще. Я использую это на отдельной странице wpf.

Я думаю, что проблема в моем контексте данных, связанном с полем со списком, я пробовал даже с разбросанным полем со списком, с привязкой, упомянутой выше, но она не работает.

Когда я использую AUTOGENERATED = true, поле со списком будет красиво создано с выбранным значением.

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

Наконец я нашел лучший и более простой ответ на свой вопрос, позвольте мне поделиться с вами, ребята:

Нам нужно определить класс как источник данных нашего поля со списком. Таким образом, все поля со списком должны иметь эти данные, и затем на основе свойства, которое мы устанавливаем (из источника данных сеток данных), должно быть выбрано и показано значение. Также нам нужно определить ресурс поля со списком в верхней части страницы или окна.

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

ПРИМЕЧАНИЕ: здесь я использовал Ключ и Значение для выбранных и отображаемых элементов. важно, даже ключ и значение неверны. ДОЛЖНО быть Значение и Ключ , с заглавными буквами . Я выложил более простую версию, не перечисляя участников, это не имеет никакого значения. Вы можете создать свой список членов enum, а затем добавить его в свой класс viewmodel. Не имеет значения, имеет ли ваш класс viewmodel другие свойства. просто обязательно верните 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"));
    }
    }

Благодаря предыдущему ответу и двум ссылкам, которые мне помогли:

1024 * связывание *

статический ресурс

0 голосов
/ 14 апреля 2019

если я понял, что вы хотите (иначе я уничтожу ответ): вот решение с использованием таблицы данных с выпадающим списком с использованием enumlist: для этого я использую 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: универсальный файл для перехвата описания файла enum

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>     
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...