Что я делаю не так с моим ItemsControl и привязкой данных? - PullRequest
1 голос
/ 01 июня 2010

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

Насколько я понимаю, для каждого байта в коллекции "backend" (наследуется от ObservableCollection) мой ItemsControl должен применять DataTemplate к ресурсам. Этот шаблон - просто текстовое поле с привязкой к конвертеру значений. Поэтому я ожидаю увидеть строку текстовых полей, каждое из которых содержит строковое представление из одного байта. Когда я использую этот XAML, я получаю только одну строку не редактируемого текста, которая, насколько я могу судить, не использует текстовое поле. Что я делаю не так?

Я вставил свой XAML ниже, удалив ненужные части (объявление меню, схему и т. Д.).

<Window ...>
        <Window.Resources>
            <local:Backend x:Key="backend" />
            <local:ByteConverter x:Key="byteConverter" />
            <DataTemplate DataType="byte">
                <TextBox Text="{Binding Converter={StaticResource byteConverter}}" />                    
            </DataTemplate>
        </Window.Resources>
        <StackPanel>
            <ItemsControl ItemsSource="{Binding Source={StaticResource backend}}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </StackPanel>
    </Window>

1 Ответ

4 голосов
/ 01 июня 2010

Вы хотите обойти конвертер значений по умолчанию для имен типов, когда вы используете типы вне пространства имен по умолчанию. И вы также хотите использовать имя типа, которое возвращается GetType(), а не имя типа, которое использует компилятор C #.

Сначала убедитесь, что вы объявили префикс пространства имен, который ссылается на пространство имен System, например:

xmlns:sys="clr-namespace:System;assembly=mscorlib"

А в вашем DataTemplate укажите тип, используя расширение разметки Type:

DataType="{x:Type sys:Byte}"

Редактировать

Вот минимальный рабочий пример:

<Window x:Class="ByteTemplateDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:ByteTemplateDemo="clr-namespace:ByteTemplateDemo" Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <DockPanel.Resources>
            <ByteTemplateDemo:ByteConverter x:Key="ByteConverter"/>
            <DataTemplate DataType="{x:Type sys:Byte}">
                <TextBox Foreground="Red" Text="{Binding Path=., Converter={StaticResource ByteConverter}}"/>
            </DataTemplate>
        </DockPanel.Resources>
        <ItemsControl x:Name="Items" ItemsSource="{Binding}"/>
    </DockPanel>
</Window>

Значение преобразователя:

public class ByteConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Byte b = (Byte)value;
        return "b" + b.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string strValue = value as string;
        Byte result;
        if (Byte.TryParse(strValue, out result))
        {
            return result;
        }
        return DependencyProperty.UnsetValue;
    }
}

А в коде позади:

public MainWindow()
{
    InitializeComponent();
    ObservableCollection<byte> bytes = new ObservableCollection<byte>();
    bytes.Add(11);
    bytes.Add(12);
    bytes.Add(13);
    bytes.Add(14);
    Items.DataContext = bytes;
}

Это показывает, что шаблон и преобразователь значений используются (так как вы увидите текстовые поля с красными значениями, которые начинаются с "b" на экране).

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

...