2013-04-01 4 views
7

저는 XAML을 처음 접했지만 익숙하게 배우고 있습니다. 내가 정말로 고민하는 것은 DataTemplate에있는 요소에 속성을 바인딩하는 것입니다.XAML : DataTemplate에서 속성 바인딩

내 문제를 설명하기 위해 간단한 WPF 예제를 만들었습니다.

이 예제에서는 에있는 CheckBoxVisibility 속성을 내 viewmodel의 속성에 바인딩하려고합니다. (이 시나리오를 사용하여 학습/데모 용으로 만 사용하십시오.)

간단한 데이터 모델 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 아래 몇 가지 추가 컨트롤을 추가하여 모든 것을 작동 함을 증명했습니다.

또한 Jeff Wilcox의 값 변환기도 구현했습니다. 데이터 템플릿 내부의 Checkbox이 변경되지, 아아, 내가 응용 프로그램을 실행하면 DataTemplate 함수 외부 컨트롤이 예상대로 확인하고 '숨기기 확인란'을 선택 해제, http://www.jeff.wilcox.name/2008/07/visibility-type-converter/

을 (. 주셔서 감사합니다)하지만.

내가 성공 있었 :

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

을하지만 난 그냥 다른 컨트롤을 모방하지만 값을 기준으로 의사 결정을 내릴려고하고 있지 않다.

제공 할 수있는 도움이나 조언에 정말로 감사드립니다.

감사합니다.

+0

Visual Studio의 디버그 출력 창에 바인딩 오류가 있습니까? 그것들은 대개 잘못되는 것을 잘 보여줍니다. – ChrisF

+0

Chris. 귀하의 회신에 감사드립니다. 출력 창을 점검했고, 의심되는 것처럼 오류가있었습니다. IsCheckBoxVisible을 찾을 수 없습니다. Duncan의 답변에 따라 적용된 수정 사항이 아래에 모두 나와 있습니다. 고맙습니다. – Dowse

답변

15

DataTemplate에있을 때 DataContext는 데이터 템플릿 개체이며,이 경우 Item입니다. 따라서 DataTemplate에있는 CheckBox의 DataContext는 ItemViewModel이 아닌 Item입니다. <TextBlock Text="{Binding ItemName}"/>Item 클래스의 속성에 바인딩됩니다. IsCheckBoxVisible에 바인딩하면 Item에 IsCheckBoxVisible이라는 속성을 찾으려고합니다.

이 주위에 몇 가지 방법이 있지만 지금까지 가장 쉬운이하는 것입니다 : IT 및 X를 제공합니다 (XAML에서) 당신의 창에

을 이름.예 :

<Window [...blah blah...] 
     x:Name="MyWindow"> 
당신은 다음과 같이 바인딩을 변경

:

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

우리는, 바인딩의 소스로 윈도우를 사용하고 다음 (당신의 ItemViewModel을해야하는 자신의 DataContext 속성을보고, 다음 IsCheckBoxVisible 속성을 쳤다. 당신은 애호가 무언가를 원하는 경우

또 다른 옵션은, 당신의 DataContext를 참조하는 프록시 개체를 사용하는 것입니다. this article on DataContextProxy를 참조하십시오.

+1

던컨. 신속한 회신에 감사드립니다. 나는 당신의 제안을 시도했고 매력처럼 작동했습니다. 나는 체크 박스를 위해 별도의 태그를 추가하는 것이 효과가있을 것이라고 생각했지만, 아아, 아니. 다시 한번 감사드립니다. Dan Wahlin의 atricle에 제공 한 링크를 읽어 줄 것입니다. (나는 당신의 대답을 표결하는 것을 시도했다. 그러나 나의 낮은 평판은 나를 그렇게하지 못하게한다.) – Dowse

+0

기쁜 I 도움이 될 수 있었다! :-) 이것은 완전히 관련이 없지만, 여러분의 의견에 비추어 볼 때, 요소의 DataContext를 수동으로 설정하면 (Window 나 다른 루트를 제외하고) 매우 조심해야 할 것입니다. 뭔가 잘못하고있어. 귀하의 시도가''행을 따른 것이라고 상상하고 있습니다 : 만약 그렇다면, xaml에서 ItemViewModel을 정의 할 때 * 생성하는 것과 같은 이유가 있습니다 * 하나, 다른 인스턴스를 가질 수 있습니다. 당신은이 문제를 해결할 수 있지만 제가 설명한 해결책이 더 낫습니다. –

관련 문제