2013-04-01 5 views
7

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

Я создал простой пример WPF, чтобы (надеюсь) объяснить мою проблему.

Я этот пример я пытаюсь связать Visibility свойства CheckBox в DataTemplate к собственности в моем ViewModel. (Использование этого сценария исключительно для обучения/демонстрации.)

У меня есть простой DataModel с именем Item, но он мало важен для этого примера.

class Item : INotifyPropertyChanged 
{ 

    // Fields... 
    private bool _IsRequired; 
    private string _ItemName; 

И довольно простая модель просмотра с именем ItemViewModel.

class ItemViewModel : INotifyPropertyChanged 
{ 
    private ObservableCollection<Item> _Items; 
    private bool _IsCheckBoxChecked; 
    private bool _IsCheckBoxVisible; 

    public ObservableCollection<Item> Items 
    { 
     get { return _Items; } 
     set { _Items = value; } 
    } 


    public bool IsCheckBoxChecked 
    { 
     get { return _IsCheckBoxChecked; } 
     set 
     { 
      if (_IsCheckBoxChecked == value) 
       return; 
      _IsCheckBoxChecked = value; 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxChecked")); 
       PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible")); 
      } 
     } 
    } 


    public bool IsCheckBoxVisible 
    { 
     get { return !_IsCheckBoxChecked; } 
     set 
     { 
      if (_IsCheckBoxVisible == value) 
       return; 
      _IsCheckBoxVisible = value; 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible")); 
     } 

(Конструкторы и INotifyPropertyChanged реализация для краткости опущены.)

управления, изложенные в MainPage.xaml следующим образом.

<Window.Resources> 
    <local:VisibilityConverter x:Key="VisibilityConverter"/> 
</Window.Resources> 

<Window.DataContext> 
    <local:ItemViewModel/> 
</Window.DataContext> 

<Grid> 
    <StackPanel> 
     <CheckBox x:Name="checkBox" Content="Hide CheckBoxes" FontSize="14" IsChecked="{Binding IsCheckBoxChecked, Mode=TwoWay}" /> 
     <ListView ItemsSource="{Binding Items}" HorizontalContentAlignment="Stretch" > 
      <ListView.ItemTemplate > 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <TextBlock Text="{Binding ItemName}"/> 
         <CheckBox Grid.Column="1" Visibility="{Binding IsCheckBoxVisible, Converter={StaticResource VisibilityConverter}}" > 
          <CheckBox.DataContext> 
           <local:ItemViewModel/> 
          </CheckBox.DataContext> 
         </CheckBox> 
        </Grid> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
     <StackPanel Orientation="Horizontal" Margin="4,4,0,0"> 
     <TextBlock Text="IsCheckBoxVisible:"/> 
      <TextBlock Text="{Binding IsCheckBoxVisible}" Margin="4,0,0,0" FontWeight="Bold" /> 
     </StackPanel > 
     <Button Content="Button" Visibility="{Binding IsCheckBoxVisible, Converter={StaticResource VisibilityConverter}}" Margin="4,4,4,4"/> 
    </StackPanel> 

</Grid> 

Флажок «Скрыть флажки» связан с IsCheckBoxChecked и используется для обновления IsCheckBoxVisible. Я также добавил несколько дополнительных элементов управления ниже DataTemplate, чтобы доказать, что все работает.)

Я также внедрил конвертер ценностей Джеффа Уилкокса. (Спасибо.) http://www.jeff.wilcox.name/2008/07/visibility-type-converter/

Когда я запустить приложение, проверку и убрав «Скрыть Checkbox», контроль за пределами функции DataTemplate, как ожидалось, но, увы, Checkbox внутри шаблон данных остается неизменными.

Я имел успех:

IsVisible="{Binding IsChecked, Converter={StaticResource VisibilityConverter}, ElementName=checkBox}" 

Но я не просто пытаюсь имитировать другой контроль, но принимать решения, основанные на стоимости.

Я бы ДЕЙСТВИТЕЛЬНО оценил любую помощь или совет, которые вы можете предложить.

спасибо.

+0

Получаете ли вы какие-либо ошибки привязки в окне вывода отладки в Visual Studio? Они, как правило, являются хорошим показателем того, что происходит не так. – ChrisF

+0

Крис. Спасибо за ваш ответ. Проверяли окна вывода и, как вы подозревали, были ошибки. Он не мог «найти» IsCheckBoxVisible. Применяется исправление в соответствии с ответом Дункана ниже и все хорошо сейчас. Спасибо. – Dowse

ответ

15

Когда вы находитесь в DataTemplate, ваш DataContext является шаблоном данных, в данном случае Item. Таким образом, DataContext CheckBox в DataTemplate - это Item, а не ваш ItemViewModel. Вы можете увидеть это на своем <TextBlock Text="{Binding ItemName}"/>, который привязывается к свойству класса Item. Привязка к IsCheckBoxVisible пытается найти свойство, называемое IsCheckBoxVisible, на Item.

Есть несколько способов обойти это, но, безусловно, проще всего сделать это:

на вашем окне (в XAML), дать ему и х: Имя.Например:

<Window [...blah blah...] 
     x:Name="MyWindow"> 

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

<CheckBox Grid.Column="1" 
      Visibility="{Binding DataContext.IsCheckBoxVisible, ElementName=MyWindow, Converter={StaticResource VisibilityConverter}}"> 

Мы используем окно в качестве источника для связывания, а затем, глядя на его имущество DataContext (который должен быть вашим ItemViewModel, а затем стаскивать IsCheckBoxVisible свойство.

Другой вариант, если вы хотите что-то любитель, чтобы использовать прокси-объект для ссылки на свой DataContext см. this article on DataContextProxy.

+1

Дункан. Спасибо за быстрый ответ. Я попробовал ваше предложение, и это сработало как шарм. Я думал, что добавление отдельного тега для флажка будет работать, но, увы, нет. Еще раз спасибо. Дайте атрику Дэна Вахлина прочитать в ссылке, которую вы предоставили. (Я пробовал проголосовать за ваш ответ, но моя низкая репутация мешает мне это делать.) – Dowse

+0

Рад, что я мог помочь! :-) Это не совсем актуально, но так же, как и в стороне, из вашего комментария: ручная настройка DataContext элемента (кроме окна или другого корня) - это то, с чем вы хотите быть очень осторожным, и часто является признаком того, что вы «что-то не так. Я предполагаю, что ваша попытка выполнялась по строкам '': если это так, причина, по которой это не сработает, - это когда вы определяете ItemViewModel в xaml, как будто вы * создаете * one, так что у вас будет другой экземпляр. Вы можете обойти это, но решение, которое я описал, лучше. –

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