WPF: вложенные свойства зависимостей

У меня есть ObservableCollection "Layouts" и DependencyProperty "SelectedLocation" в окне. SelectedLocation имеет свойство под названием «Макет», которое представляет собой объект, содержащий такие поля, как «Имя» и т. д. Я пытаюсь привязать поле со списком к SelectedLayout, но оно не работает. Следующее не работает, вместо этого я пытался привязать к SelectedItem, но безрезультатно. Я полагаю, что это может быть как-то связано с тем фактом, что я привязываюсь к подсвойству SelectedLocation DependencyProperty (хотя это реализует INotifyPropertyChanged.

<ComboBox Grid.Row="2" Grid.Column="0" x:Name="cboLayout" ItemsSource="{Binding Layouts,ElementName=root}" SelectedValue="{Binding SelectedLocation.Layout.LayoutID,ElementName=root}" DisplayMemberPath="{Binding Name}" SelectedValuePath="LayoutID" />

Однако следующие работы (также привязаны к DP "SelectedLocation":

<TextBox Grid.Row="4" Grid.Column="1" x:Name="txtName" Text="{Binding SelectedLocation.Name,ElementName=root,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

person Echilon    schedule 06.05.2011    source источник
comment
1) просьба не ставить теги в заголовке сообщения. 2) Ищите ошибки привязки, они, вероятно, дадут вам представление о том, что происходит. Вы можете найти их в окне вывода отладки Visual Studio. Альтернативное решение — использовать превосходный Snoop, чтобы просмотреть визуальное дерево вашего приложения и найти ошибки привязки.   -  person Jonas Van der Aa    schedule 06.05.2011


Ответы (1)


Какой тип имеет свойство Layouts? Я полагаю примерно так: IEnumerable<Layout>. Но вы привязываете выбранное значение к Layout.LayoutID. Итак, у вас возникла ситуация, когда поле со списком содержит Layout объектов, а вы пытаетесь выбрать его по Int идентификатору. Конечно, механизм привязки не может найти там никаких Int.

Я понятия не имею о деталях вашего кода, поэтому могу предложить одно: попробуйте уменьшить выражение привязки: SelectedItem="{Binding SelectedLocation.Layout,ElementName=root}.

Если не получилось, предоставьте больше кода, чтобы помочь мне понять, что происходит.

====ОБНОВЛЕНИЕ====

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

Макет класса, который предоставляет свойство LayoutId:

public class Layout
{
    public Layout(string id)
    {
        this.LayoutId = id;
    }

    public string LayoutId
    {
        get;
        private set;
    }

    public override string ToString()
    {
        return string.Format("layout #{0}", this.LayoutId);
    }
}

Класс SelectionLocation, который имеет вложенное свойство Layout:

public class SelectedLocation : INotifyPropertyChanged
{
    private Layout _layout;

    public Layout Layout
    {
        get
        {
            return this._layout;
        }
        set
        {
            this._layout = value;
            this.OnPropertyChanged("Layout");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        var safeEvent = this.PropertyChanged;
        if (safeEvent != null)
        {
            safeEvent(this, new PropertyChangedEventArgs(name));
        }
    }
}

И класс Window со свойствами зависимостей (на самом деле в моем примере StartupView — это UserControl, но это не имеет значения):

public partial class StartupView : UserControl
{
    public StartupView()
    {
        InitializeComponent();

        this.Layouts = new Layout[] { new Layout("AAA"), new Layout("BBB"), new Layout("CCC") };
        this.SelectedLocation = new SelectedLocation();
        this.SelectedLocation.Layout = this.Layouts.ElementAt(1);
    }

    public IEnumerable<Layout> Layouts
    {
        get
        {
            return (IEnumerable<Layout>)this.GetValue(StartupView.LayoutsProperty);
        }
        set
        {
            this.SetValue(StartupView.LayoutsProperty, value);
        }
    }

    public static readonly DependencyProperty LayoutsProperty =
        DependencyProperty.Register("Layouts",
            typeof(IEnumerable<Layout>),
            typeof(StartupView),
            new FrameworkPropertyMetadata(null));

    public SelectedLocation SelectedLocation
    {
        get
        {
            return (SelectedLocation)this.GetValue(StartupView.SelectedLocationProperty);
        }
        set
        {
            this.SetValue(StartupView.SelectedLocationProperty, value);
        }
    }

    public static readonly DependencyProperty SelectedLocationProperty =
        DependencyProperty.Register("SelectedLocation",
            typeof(SelectedLocation),
            typeof(StartupView),
            new FrameworkPropertyMetadata(null));
}

XAML StartupView:

<UserControl x:Class="Test.StartupView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:self="clr-namespace:HandyCopy"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Name="Root">
    <WrapPanel>
        <ComboBox ItemsSource="{Binding Path=Layouts,ElementName=Root}"
                  SelectedItem="{Binding Path=SelectedLocation.Layout, ElementName=Root}"/>
    </WrapPanel>
</UserControl>
person Alex Zhevzhik    schedule 06.05.2011
comment
Я пробовал это. LayoutID — это строковое свойство, которое является уникальным идентификатором. Свойство Layouts представляет собой ObservableCollection объектов Layout, каждый из которых имеет свойство LayoutID. - person Echilon; 06.05.2011
comment
Неважно. Вы сделали очевидную ошибку: невозможно выбрать значение по строке, когда ваши элементы являются Layout. Еще одна странность заключается в использовании SelectedValue вместо SelectedItem. Попробуйте последний и дайте мне знать. - person Alex Zhevzhik; 06.05.2011
comment
Я пробовал SelectedValue и SelectedItem с SelectedValuePath и без него, но, похоже, ничего не работает. - person Echilon; 06.05.2011