Не могу обернуть голову вокруг привязки данных wpf - PullRequest
0 голосов
/ 19 мая 2009

Мой сценарий: Форма wpf имеет текстовое поле и набор инструментов wpf datagrid . Когда текст вводится в текстовое поле, моя служба возвращает IEnumerable<TranslationItem> элементов. Я хочу, чтобы мой datagrid показывал результат этого сервиса.

Я пытался погуглить, но не могу понять, как это сделать. Я только начинаю изучать WPF, и большинство используемых терминов ускользает от меня.
Я понял, что я должен поместить результат моей службы в коллекцию ObservableCollection, без пота. Но затем я хочу как-то связать его с моей сеткой данных. Как я могу это сделать? Как сетка узнает, какие столбцы генерировать?

Ответы [ 4 ]

3 голосов
/ 19 мая 2009

Что я понял, так это то, что я должен поместить результат моей службы в коллекцию ObservableCollection, без пота Но затем я хочу как-то связать его с моей сеткой данных. Как я могу это сделать?

Самый простой способ - установить для свойства ItemsSource DataGrid значение ObservableCollection.

Как сетка узнает, какие столбцы генерировать?

DataGrid отражает объекты в этой коллекции и создает столбец для каждого открытого свойства, которое он находит. См. здесь для получения дополнительной информации.

Если вы устанавливаете свойство ItemsSource напрямую, то это на самом деле не привязка wpf. Вот три ссылки, которые я нашел полезными, когда начал связывать данные в WPF.

Bea Stollnitz: Что означает «{Binding}»?
Часто задаваемые вопросы по связыванию основных данных WPF
MSDN: инструкции по связыванию данных

2 голосов
/ 20 мая 2009

Хотя для этого можно использовать коллекцию ObservableCollection, в зависимости от того, как она используется, вы не получите от нее никаких выгод. Ключевой особенностью ObservableCollection является то, что она реализует INotifyCollectionChanged. Этот интерфейс предоставляет механизм уведомлений, чтобы сообщить UI, что свойство изменилось. Поскольку ObservableCollection уже реализует это, если вы связываете свойство ItemSrid, ListBox, ItemsControl и т. Д. ItemSource с коллекцией этого типа, оно будет автоматически обновлять пользовательский интерфейс при каждом добавлении / удалении / замене / перемещении / сбросе элемента. Из-за этого каждый раз, когда вы хотите обновить коллекцию новым набором результатов IEnumerable, вам придется сначала очистить коллекцию, а затем добавить новые результаты.

Однако в этом случае я бы порекомендовал еще один вариант, отличный от ObservableCollection. Это использовать то, что называется ObjectDataProvider. Используя это, мы можем полностью избежать кода, и в целом он намного чище. Так что у нас где-то есть наш сервис, в данном случае в моем Window.xaml.cs

public class TranslationService
{
    public IEnumerable<string> Translate(string s)
    {
        return s.ToCharArray().Select(c => c.ToString());
    }
}

Как и служба, которую вы описываете, она берет строку из текстового поля и возвращает IEnumerable. Теперь в XAML мы можем использовать этот сервис и совершать звонки на него.

В окне настроек мы добавляем пространство имен, в котором расположен сервис:

 xmlns:local="clr-namespace:WpfApplication4"

Теперь в наших Window.Resources (или UserControl, или где-либо еще) мы можем ссылаться на наш сервис. Как только мы представим наш сервис как ресурс, мы можем создать ObjectDataProvider, который предоставляет метод Translate, который мы хотим использовать.

<Window.Resources>
    <local:TranslationService x:Key="MyTranslationService" />
    <ObjectDataProvider x:Key="MyProvider"
                        ObjectInstance="{StaticResource MyTranslationService}"
                        MethodName="Translate">
        <ObjectDataProvider.MethodParameters>
            ""
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

ObjectDataProvider связан с нашим Сервисом и вызывает метод Translate с параметром String. Теперь все, что нам нужно сделать, это заставить его ответить на наше текстовое поле.

Мы можем сделать это, используя некоторые свойства Binding. Мы хотим, чтобы наш TextProperty в TextBox связывался с ObjectDataProvider, поэтому мы устанавливаем свойство Source, чтобы указывать на него. Часть ObjectDataProvider, которую мы хотим связать в Path, это MethodParameter. Теперь мы установили для него значение «Привязывать напрямую к источнику этого свойства» и перемещать только в одну сторону, а это означает, что параметр метода ObjectDataProvider не будет обновлять текст TextBox. Наконец, мы можем установить UpdateSourceTrigger в PropertyChanged, сообщая привязке установить источник, к которому мы привязываемся, в поставщике данных объекта, всякий раз, когда есть какие-либо изменения в тексте.

<StackPanel>
        <TextBox TextChanged="OnTextChanged"
            Text="{Binding Source={StaticResource MyProvider}, Path=MethodParameters[0], BindsDirectlyToSource=True, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
        <ListBox ItemsSource="{Binding Source={StaticResource MyProvider}}" />
    </StackPanel>

Осталось только установить ItemsSource в Grid или простой ListBox в этом случае.

Относительно заключительной части в DataGrid: Если вы используете сетку данных WPFToolkit, у нее есть функция автоматического создания, которую можно установить через свойства, и вы можете найти больше информации об этом здесь .

0 голосов
/ 19 мая 2009

ваша сетка может либо строить столбцы напрямую, либо вы можете указать типы столбцов, которые вы хотите. Если вы посмотрите это видео , оно вам все объяснит. Это для VS2010, но основные принципы те же, что и для VS2008 - хотя реализация немного отличается, так как она не так интегрирована.

Что касается того, как связывать, присвойте ObservableCollection, которая содержит ваши элементы, свойству ItemsSource сетки.

0 голосов
/ 19 мая 2009

Вы устанавливаете DataSource (или даже DataContext) сетки в свою Наблюдаемую Коллекцию.

Я не знаком с этой сеткой данных, но большинство сеток имеют опции, чтобы либо представить все общедоступные свойства типа в наблюдаемой коллекции как столбцы, либо вы явно задаете макет столбца в XAML и одно из свойств Определение столбца - это свойство объекта, используемого для данных столбца.

например. с сеткой данных Infragistics

                <igDP:Field Name="OrderSize" Label="Order Size">
                    <igDP:Field.Settings >
                        <igDP:FieldSettings CellWidth="75">
                            <igDP:FieldSettings.EditorStyle>
                                <Style TargetType="{x:Type Editors:ValueEditor}" >
                                    <Style.Setters>
                                        <Setter Property="Format" Value="#,##0"/>
                                    </Style.Setters>
                                </Style>
                            </igDP:FieldSettings.EditorStyle>
                        </igDP:FieldSettings>
                    </igDP:Field.Settings>
                </igDP:Field>

Имя - это то, где вы задаете свойство для объекта.

...