2015-01-16 3 views
1

잠시 동안 WPF를 사용하는 경우 실제로 항목 외의 속성을 기반으로 구성 할 수있는 ListBox에 대한 ItemTemplate이있는 상황이 처음입니다. 사용자가 글꼴 미리보기를 활성화하기 위해 chechbox를 클릭 할 수있는 글꼴 선택기 대화 상자를 원할 때 문제가 발생했습니다. 실제로이 구현에 대해 마음이 바뀌었지만 여전히 대답을 알고 싶습니다.Item 분리를 위반하지 않고 ItemTemplate을 구성하는 표준 방법은 무엇입니까?

DataTemplate은 해당 유형이 제공되는 모든 상황에서 사용할 수 있기 때문에 아이템 구성 외부의 매개 변수에 바인딩하지 않는 것이 좋습니다 (포함 된 DataTemplate의 속성에 바인딩하는 코드처럼 보입니다). 특히 무뚝뚝합니다.)이 상황을 어떻게 구현했는지 궁금합니다. 아래 코드는 작동하지만 바인딩은 시각적 요소에 바인딩되는 반면 ViewModel에서는 속성에 바인딩됩니다.

<Window x:Class="ScreenWriter.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}" > 
    <Grid> 
     <StackPanel> 
      <CheckBox Name="ShowPreview" IsChecked="{Binding IsShowPreviewChecked}"> 
       Show Preview 
      </CheckBox> 
      <ListBox ItemsSource="{Binding Source={x:Static Fonts.SystemFontFamilies}}"> 
       <ListBox.ItemTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding}"> 
          <TextBlock.Style> 
           <Style> 
            <Setter Property="TextBlock.FontFamily" Value="Arial" /> 
            <Style.Triggers> 
             <DataTrigger Value="True" Binding="{Binding IsChecked, ElementName=ShowPreview}"> 
              <Setter Property="TextBlock.FontFamily" Value="{Binding}"/> 
             </DataTrigger> 
            </Style.Triggers> 
           </Style> 
          </TextBlock.Style> 
         </TextBlock> 
        </DataTemplate> 
       </ListBox.ItemTemplate> 
      </ListBox> 
     </StackPanel> 
    </Grid> 
</Window> 

이 비정상적인 상황은 아닌 것 같아,하지만 난로 시작되지 않은 솔루션을 찾을 수 없습니다 "이것은 당신이 이렇게 안하는지 주위에 얻을 수있는 현명한 방법입니다." 도움을 주셔서 감사합니다 ...

답변

0

이 문제에 대한 최상의 방법은 없습니다.

작성한대로 "DataTemplate은 해당 유형이 제공되는 모든 상황에서 사용할 수 있습니다 ... 항목의 구성 외부의 매개 변수에 바인딩하지 마십시오".

Binding/DataContext는 LogicalTree를 기반으로합니다. 따라서 트리거 바인딩은 트리에서 가장 가까운 datacontext를 찾으려고 시도합니다 (이 경우 사용자의 ListItem DataContext = FontFamily)

이 'LogicalTree Island'에서 메인 트리로 '점프' 요소는 점프를했다. 진짜 질문은 어떻게 바인딩 소스를 원활하게 변경할 수 있는가입니다.

직접 대상 요소의 DataContext를 바인딩 할 수는 (체크 박스 더의 DataContext가 없습니다, 그러나 그것의 조부모 - 윈도우가) :

<DataTrigger Binding="{Binding DataContext.IsShowPreviewChecked, ElementName=ShowPreview}" Value="True" >  

를하거나 직접하여 ListItem 조상을 찾을 :

<DataTrigger Binding="{Binding DataContext.IsShowPreviewChecked, RelativeSource={RelativeSource AncestorType=ListBox, Mode=FindAncestor}}" Value="True" > 

사용됩니다 이 점프 여러 번, 당신은 BindingProxy 귀하의 바인딩에 대한 지름길을 제공 할 사용하려고합니다 :

public class BindingProxy : Freezable 
{ 
    protected override Freezable CreateInstanceCore() 
    { 
     return new BindingProxy(); 
    } 

    public object Context 
    { 
     get { return (object)GetValue(ContextProperty); } 
     set { SetValue(ContextProperty, value); } 
    } 

    public static readonly DependencyProperty ContextProperty = 
     DependencyProperty.Register("Context", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 
}  

Resouce의로이 프록시를 추가

<Window.Resources> 
    <this:BindingProxy x:Key="Proxy" Context="{Binding}" /> 
</Window.Resources> 

을하고 바인딩은 다음과 같습니다

<DataTrigger Binding="{Binding Context.IsShowPreviewChecked, Source={StaticResource Proxy}}" Value="True" >  

당신의 ViewModel

인터페이스에서 INotifyPropertyChanged 추가 잊지 마세요