Привязка элементов управления C # WPF к словарю - PullRequest
1 голос
/ 29 сентября 2011

Привет :) Я только изучаю C # и WPF, и мне нужно написать инструмент, который:

  1. Загружает файл данных (строка Key, int Value)
  2. Привязывает данные к пользовательскому интерфейсу WPF для редактирования
  3. Сохраняет новый файл данных

Моя мысль - словарь - будет лучше. Данные загружаются из файла только один раз, а изменения вносятся только с помощью элементов управления WPF. Я пробовал много вещей, но я все еще продолжаю преодолевать препятствия, когда связываю данные с элементами управления. Я работал с упрощенной версией инструмента - ниже. Данные привязываются к элементу управления WPF, но нет события изменения для обновления словаря. Я не нашел хорошего примера для подражания. Может кто-нибудь объяснить, как заставить словарь обновляться? И правильная ли стратегия? - используя словарь - используя DataContext. Если вы хотите увидеть полный проект и пользовательский интерфейс - внизу есть ссылка. Я работал много-много дней ... с прогрессом, но я слишком медленный;) ура Дэнни

MainWindow.xaml

<Window x:Class="configGen.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="200" Width="150">
<StackPanel Margin="20" Width="80">
    <TextBox Text="{Binding [item1]}" />
    <TextBlock Text="{Binding [item1]}" />
    <TextBox Text="{Binding [item2]}" />
    <TextBlock Text="{Binding [item2]}" />
    <TextBox Text="{Binding [item3]}" />
    <TextBlock Text="{Binding [item3]}" />
    <Slider Value="{Binding [item4]}" Minimum="0" Maximum="256" />
    <TextBlock Text="{Binding [item4]}" />
</StackPanel>    

MainWindow.xaml.cs

namespace configGen
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            dataClass record = new dataClass();
            DataContext = record.generate();
        }
    }

    public class dataClass
    {
        public Dictionary<string, int> generate()
        {
            Dictionary<string, int> _data = new Dictionary<string, int>();
            _data.Add("item1", 100);
            _data.Add("item2", 120);
            _data.Add("item3", 140);
            _data.Add("item4", 160);
            return _data;
        }
    }
}

Ссылка на полный проект ...

http://www.baytower.ca/btsRV7config.zip


Спасибо всем за отличные отзывы !! Я вернусь к работе:)

Ответы [ 4 ]

1 голос
/ 29 сентября 2011

Словарь - определенно не удобный способ связывания данных в WPF. Кажется, ObservableCollection больше соответствует вашим требованиям.

Что-то вроде:

public class ItemsList : ObservableCollection<Item>
{
    public ItemsList() : base()
    {
        Add(new Item("item 1", 100));
        Add(new Item("item 2", 120));
        Add(new Item("item 3", 140));
        Add(new Item("item 4", 160));
    }
  }

Item - это простой класс со свойствами имени и значения. Я пропустил это здесь, потому что это говорит само за себя.

Преимущество здесь в том, что вы можете привязать к динамическому числу элементов, а не только те, которые объявлены обязательно.

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

Ваш XAML должен будет измениться, чтобы обеспечить привязку к коллекции, конечно. Возможно ItemsControl, который принимает эту коллекцию за ItemsSource.

1 голос
/ 29 сентября 2011

Вот пример того, как я бы это сделал.

Основной класс (код сзади)

 /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private List<MyObject> _myObjects;
        public List<MyObject> MyObjects
        {
            get { return _myObjects; }
            set 
            {
                _myObjects = value;
                if(PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("MyObjects"));
                }
            }
        }


    public MainWindow()
    {
        MyObjects = new List<MyObject>();

        // Add 20 records for sample data
        for (int i = 0; i < 20; i++)
        {
            MyObject o = new MyObject();
            o.Label = string.Format("Key{0}", i);
            o.MyValue = string.Format("Value{0}", i);    
            MyObjects.Add(o);
        }
        InitializeComponent();
        DataContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

вторичный класс

public class MyObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _label;
    public string Label
    {
        get { return _label; }
        set
        {
            _label = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Label"));
            }
        }
    }

    private string _myValue;
    public string MyValue
    {
        get
        {
            return _myValue;
        }
        set
        {
            _myValue = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("MyValue"));
            }
        }
    }
}

Файл XAML

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="listboxstyle">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Path=Label}" />
                <TextBox Grid.Column="1" Text="{Binding Path=MyValue}" />
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid>       

        <ListBox
            ItemsSource="{Binding Path=MyObjects}"
            ItemTemplate="{StaticResource listboxstyle}"
            />

    </Grid>
</Window>
1 голос
/ 29 сентября 2011

Вместо использования словаря в качестве DataContext я бы создал пользовательский объект, такой как MainViewModel.Присвойте ему свойства, соответствующие item1, item2 и т. Д., За исключением того, что присвойте им соответствующие имена.Затем используйте <TextBox Text="{Binding MyPropertyName}" />.Для обработки обновлений вы можете либо установить DataContext для нового объекта MainViewModel, либо настроить класс для трансляции изменений свойств.Вы можете сделать это либо через INotifyPropertyChanged в классе, либо с помощью свойств зависимостей .

По крайней мере, это то, что вы пытаетесь достичь.Если вы собираетесь отображать произвольное количество элементов управления, вам нужно что-то другое.

0 голосов
/ 01 октября 2011

Я попробовал пример Целла, используя его класс в списке.Список - это просто удобный способ генерировать и управлять фиксированным количеством элементов.Элемент управления ItemF WPF связывается с объектом Item1 и его значением.Объект находится по его индексу.Привязка и dataContext в этом случае достаточно просты для использования (как новичка).Это работает, но я не уверен, что это действительно элегантный способ сделать это.

public MainWindow()
{
    MyObjects = new List<MyObject>();

    MyObject item1 = new MyObject();
    item1.MyValue = string.Format("100");
    MyObjects.Add(item1);

    MyObject item2 = new MyObject();
    item2.MyValue = string.Format("120");
    MyObjects.Add(item2);

    MyObject item3 = new MyObject();
    item3.MyValue = string.Format("140");
    MyObjects.Add(item3);

    MyObject item4 = new MyObject();
    item4.MyValue = string.Format("160");
    MyObjects.Add(item4);

    InitializeComponent();
    DataContext = this;
}

xaml

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Margin="20" Width="80">
        <TextBox Text="{Binding MyObjects[0].MyValue}" />
        <TextBlock Text="{Binding MyObjects[0].MyValue}" />
        <TextBox Text="{Binding MyObjects[1].MyValue}" />
        <TextBlock Text="{Binding MyObjects[1].MyValue}" />
        <TextBox Text="{Binding MyObjects[2].MyValue}" />
        <TextBlock Text="{Binding MyObjects[2].MyValue}" />
        <Slider Value="{Binding MyObjects[3].MyValue}" Minimum="0" Maximum="256" />
        <TextBlock Text="{Binding MyObjects[3].MyValue}" />
    </StackPanel>
</Window>

Кстати, я изменю на int для MyValues ​​.. онивсе целые числа.Пока это строка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...