2013-05-10 1 views
5

주 창에서 bool에 바인딩하려고합니다. 하지만 그것은 대신 내 사용자 지정 컨트롤의 데이터 컨텍스트에서 찾고 있어요. 사용자 정의 컨트롤에 DataContext를 할당하지 않으면 주 윈도우의 바인딩이 작동하지만 (분명히) 사용자 정의 컨트롤의 바인딩이 중단됩니다. 나는 두 컨트롤에서 작동하는 바인딩이 필요내 WPF 사용자 정의 컨트롤의 데이터 컨텍스트가 부모를 대신합니다

System.Windows.Data Error: 40 : BindingExpression path error: 'MyControlVisible' property not found on 'object' ''MyUserControlModel' (HashCode=1453241)'. BindingExpression:Path=MyControlVisible; DataItem='MyUserControlModel' (HashCode=1453241); target element is 'MyUserControl' (Name='_myUserControl'); target property is 'Visibility' (type 'Visibility') 

,하지만 난 사용자 컨트롤의 데이터 컨텍스트가 창의를 대체하고 싶지 않은 : 여기에 오류가 있습니다.

<Window x:Class="Sandbox.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:Controls="clr-namespace:Sandbox.Controls" Title="Sandbox"> 
    <DockPanel LastChildFill="True"> 
     <DockPanel.Resources> 
      <BooleanToVisibilityConverter x:Key="boolToVis" /> 
     </DockPanel.Resources> 
     <Grid> 
      <Controls:MyUserControl x:Name="_myUserControl" Visibility="{Binding MyControlVisible, Converter={StaticResource boolToVis}}"/> 
     </Grid> 
    </DockPanel> 
</Window> 

namespace Sandbox 
{ 
    public partial class MainWindow 
    { 
     private MainWindowModel model; 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = model = new MainWindowModel(); 
      _myUserControl.Initialize(model.MyUControlModel); 
     } 
    } 
} 

using System.ComponentModel; 
using Sandbox.Controls; 

namespace Sandbox 
{ 
    public class MainWindowModel : BaseModel 
    { 
     public MyUserControlModel MyUControlModel { get; set; } 
     public bool MyControlVisible { get; set; } 
     public MainWindowModel() 
     { 
      MyUControlModel = new MyUserControlModel(); 
      MyControlVisible = false; 
      OnChange(""); 
     } 
    } 

    public class BaseModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     protected void OnChange(string s) 
     { 
      var handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(s)); 
      } 
     } 
    } 
} 

<UserControl x:Class="Sandbox.Controls.MyUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d"> 
    <Grid> 
     <TextBlock Text="{Binding MyBoundText}"/> 
    </Grid> 
</UserControl> 

namespace Sandbox.Controls 
{ 
    public partial class MyUserControl 
    { 
     public MyUserControl() 
     { 
      InitializeComponent(); 
     } 

     public void Initialize(MyUserControlModel context) 
     { 
      DataContext = context; 
     } 
    } 

} 

namespace Sandbox.Controls 
{ 
    public class MyUserControlModel : BaseModel 
    { 
     public string MyBoundText { get; set; } 
     public MyUserControlModel() 
     { 
      MyBoundText = "Hello World!"; 
      OnChange(""); 
     } 
    } 
} 

답변

3

당신이 UserControl 자체에서 직접 DataContext을 설정해서는 안 많은 이유 중 하나입니다

여기에 코드입니다. 그렇게, 당신은 더 이상 어떤 다른 DataContext을 사용할 수 없습니다 않는 경우

해당 UserControl의 DataContext가에 하드 코딩되어 있기 때문입니다. 당신의 바인딩의 경우

, 일반적으로 DataContext는 상속 될 수 있도록 Visibility 찾을 수 바인딩 현재 DataContextMyControlVisible 속성이 있지만 사용자 컨텍스트의 DataContext을 하드 코드했기 때문에 해당 속성을 찾을 수 없습니다. 즉,이 특정 경우에 대한 문제에 대한 단지 해결 방법입니다 그러나

당신은

<Controls:MyUserControl Visibility="{Binding 
    RelativeSource={RelativeSource AncestorType={x:Type Window}}, 
    Path=DataContext.MyControlVisible, 
    Converter={StaticResource boolToVis}}" ... /> 

로, 당신의 바인딩에 그런를 다른 바인딩 소스를 지정할 수 있고, 내보기에 영구적 인 해결책이되지 않습니다. 더 나은 해결책은 단순히 UserControl을 하드 코드하지 않는 것입니다.

UserControl의 용도와 응용 프로그램 디자인 방법에 따라 몇 가지 방법이 있습니다.

  • 당신은 가치를 전달하기 위해 UserControl을에 DependencyProperty을 만들 수 있고, 그 결합.

    <Controls:MyUserControl UcModel="{Binding MyUControlModelProperty}" ... /> 
    

    <UserControl x:Class="Sandbox.Controls.MyUserControl" 
          ElementName=MyUserControl...> 
        <Grid DataContext="{Binding UCModel, ElementName=MyUserControl}"> 
         <TextBlock Text="{Binding MyBoundText}"/> 
        </Grid> 
    </UserControl> 
    
  • 아니면 만들 ​​수 귀하의 특정 속성이 DataContext에 전달받을 것이라는 기대와 UserControl. 이것은 보통 내가하는 일로 DataTemplates과 함께 사용됩니다.

    <Controls:MyUserControl DataContext="{Binding MyUControlModelProperty}" ... /> 
    

    <UserControl x:Class="Sandbox.Controls.MyUserControl"...> 
        <Grid> 
         <TextBlock Text="{Binding MyBoundText}"/> 
        </Grid> 
    </UserControl> 
    
  • 제가 위에서 말했듯이

    , 정말 일반적으로 메인 윈도우에 대한 내 XAML는 것, 자신의 DataContext에 대한 Model의 특정 유형을 기대 내 UserControls을 표시 DataTemplates를 사용하려면 다음과 같이 보입니다 :

    <DataTemplate DataType="{x:Type local:MyUControlModel}"> 
        <Controls:MyUserControl /> 
    </DataTemplate> 
    
    <ContentPresenter Content="{Binding MyUControlModelProperty}" ... />