ItemsControl ItemTemplate Binding выбирает неправильную модель представления - PullRequest
0 голосов
/ 17 апреля 2020

Я переписал вопрос:

Используя WPF и caliburn micro, моя привязка к методу "Select" выбирает неправильную модель представления, когда вызывается Select ('this' неправильный)

interface Base
{
    void Select();
    // and more, eg IsSelected, ButtonName
}

class ViewModel : Base
{
    List<Base> Items;
    void Select()
    {
        // now this=A which is wrong
    }
}

void Run()
{
    var A = new ViewModel();
    var B = new ViewModel();
    A.Items.Add(B);
}

Представление содержит это:

            <ItemsControl ItemsSource="{Binding Items}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <RadioButton Style="{StaticResource RadioButtonSelectorStyle}" GroupName="Main" Content="{Binding ButtonName}" IsChecked="{Binding IsSelected}">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Click">
                                    <cal:ActionMessage MethodName="Select" />
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </RadioButton>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>

1 Ответ

0 голосов
/ 17 апреля 2020

Если у вас смешанная или составная коллекция, при определении DataTemplate без подсказки типа путем установки DataType синтаксический анализатор XAML должен определить фактический тип данных. Теперь, если указанный (виртуальный) член определен в общем базовом классе или интерфейсе, синтаксический анализатор предполагает реализацию случайного соответствия для разрешения ссылки.

Если вы привязываете к свойствам, это поведение не имеет побочных эффектов, за исключением того, что они определены как virtual (что случается редко, поскольку свойства предназначены не для реализации поведения, а для хранения Штат). Но поскольку вы привязываетесь к методу, вы сталкиваетесь с неожиданным поведением, когда каждая реализация или специализация предоставляют свою собственную реализацию указанного метода.

Решение состоит в том, чтобы явно определить DataType из DataTemplate, особенно при работе с составными коллекциями.
Для динамического шаблонирования данных необходимо определить DataTemplate для каждого тип объекта. Вы можете определить их в ResourceDictionary в области действия ItemsControl, например ItemsControl.Resources. Поскольку шаблоны неявные (без ключа), они будут автоматически применены к текущему типу данных:

<ItemsControl>
  <ItemsControl.Resources>
    <DataTemplate DataType="{x:Type RadioButtonViewModel}>
      <RadioButton>
        <i:Interaction.Triggers>
          <i:EventTrigger EventName="Click">
            <cal:ActionMessage MethodName="Select" />
          </i:EventTrigger>
        </i:Interaction.Triggers>
      </RadioButton>
    </DataTemplate>

    <DataTemplate DataType="{x:Type ScreenViewModel}>
      <RadioButton>
        <i:Interaction.Triggers>
          <i:EventTrigger EventName="Click">
            <cal:ActionMessage MethodName="Select" />
          </i:EventTrigger>
        </i:Interaction.Triggers>
      </RadioButton>
    </DataTemplate>
  </ItemsControl.Resources>
</ItemsControl>
...