2012-05-16 5 views
0

У меня есть 3 списка, которые связаны двумя отдельными наблюдаемыми коллекциями того же типа. My ViewModel имеет видимые коллекции, открытые через свойства. Это для некоторой группы перетаскивания, в поле списка источников могут быть элементы, перетаскиваемые в два разных списка. Но я хочу дать пользователю возможность щелкнуть правой кнопкой мыши на элементе listboxitem и установить свойства элемента. Такие вещи, как «Тип», «Имя» и т. Д. Я использую шаблон данных, поскольку я хочу, чтобы все три окна были одинаковыми по функциональности. Это хорошо работает, и я могу вызвать контекстное меню, когда я нажимаю на отдельные элементы без проблем. Моя проблема в том, что у меня есть одно имя FieldType. Это перечисление, которое имеет 4 потенциальных значения. Я не могу, по моей жизни, понять, как связать свойство IsChecked с MenuItem с этим свойством ... функционально в любом случае. Вот что я пытался ....Контекстное меню для listboxitem, связанного с наблюдаемым цветом MVVM style

<DataTemplate x:Key="SFTemplateWithContextMenu"> 
     <TextBlock Text="{Binding Path=FieldName}" ><!--Tag="{Binding DataContext, ElementName=Window}"--> 
     <TextBlock.ContextMenu> 
       <ContextMenu > 
        <ContextMenu.Resources> 
         <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverterc" /> 
        </ContextMenu.Resources> 
        <MenuItem Header="Rename..." /> 
        <MenuItem Header="Field Type"> 
         <MenuItem.Resources> 
          <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" /> 
         </MenuItem.Resources> 
         <MenuItem Header="String" IsCheckable="True" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.FieldType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverterc}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/> 
         <MenuItem Header="Date" IsCheckable="True" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.FieldType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.Date}}"/> 
         <MenuItem Header="Barcode" IsCheckable="True" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Path=DataContext.FieldType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.BarCode}}" /> 
        </MenuItem> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </DataTemplate> 

В коде выше вы можете увидеть на String, Date и штрихкодов MenuItems, что я пытался сделать (надо любить код, работа в процессе) , Моя проблема - это выставленное свойство, которое оно должно вызывать. Я не знаю, как в свойстве ViewModel перейти к элементу в наблюдаемой коллекции, которая соответствует выбранному элементу. У меня есть конвертер значений EnumToBoolean, который будет сидеть на привязке, чтобы получить отметку или нет. Проблема - это свойство, которое устанавливает/получает этот конкретный элемент в наблюдаемой коллекции.

Любые мысли? Нужен больше кода? Мне нужно прояснить что-нибудь? Как близко я? Кстати, код ViewModel написан на VB 2010.

Благодарности Bryce

EDIT: Я попробовал следующее предложение с помощью Ангела ...

 <DataTemplate x:Key="SFTemplateWithContextMenu"> 
     <TextBlock x:Name="Field" Text="{Binding Path=FieldName}" > 
     <TextBlock.ContextMenu PlacementTarget="{Binding ElementName=Field}"> 
        <MenuItem Header="Rename..." /> 
        <MenuItem Header="Field Type"> 
         <MenuItem.Resources> 
          <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" /> 
         </MenuItem.Resources> 
         <MenuItem Header="Date" IsCheckable="True" IsChecked="{Binding PlacementTarget.DataContext.FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/> 
        </MenuItem> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </DataTemplate> 

Но это дает мне ошибка, которая говорит ... Невозможно установить свойства элементов свойств. Не уверен, что это проблема TextBlox vs TextBox? Вы использовали TextBox в своем примере ... я предполагаю, что ваш код будет делать то же самое. Так я тогда попробовал следующее ...

 <DataTemplate x:Key="SFTemplateWithContextMenu"> 
     <TextBlock x:Name="Field" Text="{Binding Path=FieldName}" ><!--Tag="{Binding DataContext, ElementName=Window}"--> 
     <TextBlock.ContextMenu> 
       <ContextMenu PlacementTarget="{Binding ElementName=Field}" > 
        <MenuItem Header="Rename..." /> 
        <MenuItem Header="Field Type"> 
         <MenuItem.Resources> 
          <Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" /> 
         </MenuItem.Resources> 
         <MenuItem Header="Date" IsCheckable="True" IsChecked="{Binding PlacementTarget.DataContext.FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/> 
        </MenuItem> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </DataTemplate> 

Но это вызывает обязательные ошибки ... System.Windows.Data Ошибка: 4: Не удается найти источник для связывания со ссылкой «ELEMENTNAME = Поле». BindingExpression: (нет пути); DataItem = NULL; целевой элемент - «ContextMenu» (Name = ''); target property - «PlacementTarget» (тип «UIElement»)

Таким образом, похоже, что привязка не работает. Есть предположения?

ответ

1

ContextMenu не является частью визуального дерева. Поэтому он не по умолчанию, подключение \ привязку к DataContext в TextBlock, на котором она применяется ...

SО 2 способа сделать это ...

  1. Набор ContextMenu.PlacementTarget и ссылаются на то, как Path в индивидуальном привязке MenuItem.

, например.

<TextBox x:Name="MyTextBlock"> 
     <TextBox.ContextMenu PlacementTarget="{Binding ElementName=MyTextBlock}"> 
      <MenuItem 
       Header="{Binding PlacementTarget.DataContext.MyHeader, 
            RelativeSource={RelativeSource 
             AncestorType={x:Type ContextMenu}}}" 
     </TextBox.ContextMenu> 
    </TextBox> 

Таким образом, в приведенном выше примере ... Вы хотите соединить пункт меню с контекстом данных в текстовом поле. Таким образом, вы определяете PlacementTarget на ContextMenu. Эта цель размещения может быть установлена ​​только с двумя типами привязок ...ElementName или StaticResource. И как только контекстное меню подключено к визуальному элементу через PlacementTarget, используйте Path в привязке meuitem для разрешения свойства контекста данных, то есть MyHeader.

ИЛИ

Использовать прокси-элементный подход ...

Bind datagrid column visibility MVVM

+0

Поскольку TextBox генерируется с помощью DataTemplate от привязки к наблюдаемой коллекции все они будут иметь тот же х: Name. Нужно ли уникальное имя x: Name? Разве это не запутается в отношении того, к кому нужно привязываться, если все они имеют одно и то же имя? –

+0

Имена уникально ** ограничены ** в WPF, поэтому я думаю, что подход 'ElementName' будет работать. См. Эту ссылку на namescoping ... http://msdn.microsoft.com/en-us/library/ms746659.aspx –

+0

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

Смежные вопросы