Проблемы с привязкой выпадающего списка к пользовательскому классу

#wpf #xaml #c#-4.0 #entity-framework-4

#wpf #xaml #c #-4.0 #entity-framework-4

Вопрос:

У меня возникли проблемы с моим полем со списком. Я пытаюсь установить выделение во время выполнения, но привязка не работает.

 public ICLINKDesignatorCandidate SelectedDesignator
  SelectedDesignator.Designator = somevalue;
...
<ComboBox Grid.Row="4" DisplayMemberPath="DisplayName"  
          SelectedValuePath="{Binding Path=DesignatorId}"  
          SelectedItem="{Binding Path=SelectedDesignator}"
          ItemsSource="{Binding DesignatorList}"  />
  

Итак, я получаю ошибку привязки:

Ошибка пути к BindingExpression: свойство ‘DesignatorId’ не найдено в ‘object’ «TCard4312VM’ (hashCode =47413204)’. Выражение привязки: Path=DesignatorId; DataItem=’TCard4312VM’ (hashCode =47413204); целевой элемент — ‘ComboBox’ (Name=»); целевое свойство — ‘SelectedValuePath’ (тип ‘Строка’)

Итак, ПОЧЕМУ он смотрит на родительскую модель представления вместо объекта CLINKDesignatorCandidate?

Таким образом, SelectedValuePath просматривает модель родительского представления ВМЕСТО свойства элемента в списке назначений. Странно то, что когда мой список назначений представлял собой список типа «DESIGNATOR» (который был объектом entity framework), это работало отлично, и проблем с привязкой не было.

Очевидно, что DisplayName работает правильно, поэтому я не знаю, почему DesignatorID не работает. Вот класс:

 public class CLINKDesignatorCandidate : ICLINKDesignatorCandidate
{
    public CLINKDesignatorCandidate()
    {

    }

    public int DesignatorID { get; set; }
    public DESIGNATOR Designator
    {
        get;
        set;
    }

    public string DisplayName
    {
        get;
        set;
    }


}
  

Вот код, который работал, когда я привязывался к списку обозначений типов (entity framework entity):

   <ComboBox Grid.Row="3" IsEditable="True" 
            DisplayMemberPath="DesignatorName"  
            SelectedValuePath="{Binding Id}"  
            SelectedItem="{Binding SelectedDesignator}" 
            ItemsSource="{Binding DesignatorList}"  />
  

Это работало отлично, и у меня никогда не возникало проблем с привязкой, когда он пытался искать «Id» в модели родительского представления.

Я устанавливаю модель представления в коде следующим образом:

     public New4312(IEquipment4312VM vm)
        : this()
    {

        InitializeComponent();
        this.DataContext = vm;
    }
  

Я использую DataTemplate в словаре ресурсов для поля со списком:

 <DataTemplate x:Key="resTCard4312MIP">
    <Button Tag="{Binding}" >

        <Grid DataContext="{Binding}">
            <telerik:Tile Width="100" Background="Purple">                    
                    <ComboBox Grid.Row="4"  IsEditable="True"  
                              DisplayMemberPath="DisplayName"  
                              SelectedValuePath="{Binding Path=DesignatorId}"  
                              SelectedValue="{Binding Path=SelectedDesignator.DesignatorID}"  
                              SelectedItem="{Binding Path=SelectedDesignator}"
                              ItemsSource="{Binding DesignatorList}"  />
                </Grid>
            </telerik:Tile>
etc...
  

Имейте в виду, что весь этот код работал, когда мой список назначений был списком объектов вместо пользовательского класса.

Спасибо за любую помощь. Надеюсь, я достаточно хорошо объяснил проблему.

Комментарии:

1. Форматируйте свои вопросы.

2. Что я неправильно отформатировал?

3. Вы видели все изменения? Пустые строки? Материал за пределами экрана.

4. Интересно, для меня это выглядит нормально. Ничего не исчезает с экрана.

5. Да, потому что он был отредактирован другими. Вернитесь к своему оригиналу. И в нем все еще есть пустые строки.

Ответ №1:

Идентификатор обозначения

это не то же самое, что

Идентификатор обозначения

Имена свойств чувствительны к регистру
XAML не соответствует имени свойства

Ответ №2:

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

Прямо сейчас вы привязываете это свойство к свойству вашего ComboBox.DataContext , и похоже, что ваша ошибка привязки действительно верна: в DesignatorId вашем ComboBox.DataContext элементе нет свойства с именем, которое имеет тип TCard4312VM

Измените его с привязки на строку, и он должен работать

 SelectedValuePath="DesignatorID"
  

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

  • Одна из распространенных, которые я вижу, заключается в том, что WPF может запутаться, когда вы привязываете более одного из Selected свойств ( SelectedItem , SelectedValue и SelectedIndex ). Все 3 свойства устанавливают одно и то же, какой элемент выбран, однако я считаю, что нет определенного порядка, в котором они выполняются, и установка более одного может вызвать проблемы.

    Поскольку вы привязываетесь к пользовательскому объекту, я бы предложил удалить SelectedItem свойство и сохранить только SelectedValue и (исправленные) SelectedValuePath свойства.

  • Вторая распространенная причина, по которой пользовательский элемент не выбирается, заключается в том, что WPF сравнивает SelectedItem с элементами в ItemsSource using .Equals , который по умолчанию сравнивает объекты по ссылке. Итак, если ваша SelectedItem ссылка точно такая же, как и у элемента в ItemsSource , это будет работать, однако, если это не так, он подумает, что элемент не найден, и ни один элемент не будет выбран.

    Общим решением в этом случае является либо использование SelectedValue and SelectedValuePath для настройки выбранного элемента, либо переопределение .Equals() и .GetHashCode() вашего элемента, чтобы они считались равными на основе их данных, а не ссылки.

  • И третья вещь, о которой я могу подумать, которая может быть причиной этого, я не вижу никаких уведомлений об изменениях в вашем коде. Возможно, вы оставили это для простоты, однако я часто вижу, как новые пользователи WPF забывают внедрить INotifyPropertyChanged, поэтому я подумал, что это стоит упомянуть. Уведомление PropertyChange отвечает за оповещение пользовательского интерфейса при изменении значения, чтобы он мог обновить любые привязки к этому свойству.

Ответ №3:

Итак, ПОЧЕМУ он смотрит на родительскую модель представления вместо объекта CLINKDesignatorCandidate?

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

Странно то, что когда мой список назначений представлял собой список типа «DESIGNATOR» (который был объектом entity framework), это работало отлично, и проблем с привязкой не было.

Почему-то я вам не верю. Источник элементов не должен влиять на фундаментальную механику работы системы привязки.