2017-10-27 4 views
0

재사용 가능한 UserControl을 개발하려고하지만 바인딩 문제가 발생합니다. 내가 테스트 할 수 있지만 그것을 밖으로 정렬 할 수없는 작은 응용 프로그램을 만들었습니다, 또는 적어도 그것이 내가 예상했던대로 작동하지 않는 이유를 이해합니다.WPF UserControl이 부모 DataContext를 상속하지 않습니다.

코드는 다음과 같습니다. MainWindow.xaml에 넣은 TestUserControl의 인스턴스는 TextBlock 에서처럼 DataContext를 상속받습니다. 대신 DataContext가 null 인 것으로 보입니다. DataContext가 전달되지 않는 이유가 있습니까? 자동으로 설정해야합니까?

MainWindow.xaml

<Window x:Class="WpfTestApp.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfTestApp" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel Orientation="Vertical"> 
     <local:TestUserControl TextFromParent="{Binding SomeText}" /> 
     <TextBlock Name="TestTextBlock" Text="{Binding SomeText}" /> 

    </StackPanel> 
</Window> 

MainWindow.xaml.cs를

using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using System.Windows; 

namespace WpfTestApp 
{ 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     private string _someText; 

     public MainWindow() 
     { 
      DataContext = this; 

      InitializeComponent(); 

      SomeText = "New Text!"; 
     } 

     public string SomeText 
     { 
      get { return _someText; } 
      set 
      { 
       _someText = value; 
       NotifyOnPropertyChanged(); 
      } 
     } 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected void NotifyOnPropertyChanged([CallerMemberName] string propertyName = "") 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

TestUserControl.xaml

<UserControl x:Class="WpfTestApp.TestUserControl" 
      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" 
      xmlns:local="clr-namespace:WpfTestApp" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <TextBlock Name="TheTextBlock" Text="{Binding TextFromParent}" /> 

    </Grid> 
</UserControl> 

TestUserControl.xaml.cs

using System.Windows; 
using System.Windows.Controls; 

namespace WpfTestApp 
{ 
    public partial class TestUserControl : UserControl 
    { 
     public TestUserControl() 
     { 
      InitializeComponent(); 
     } 

     public string TextFromParent 
     { 
      get { return (string)GetValue(TextFromParentProperty); } 
      set { SetValue(TextFromParentProperty, value); } 
     } 

     public static readonly DependencyProperty TextFromParentProperty = DependencyProperty.Register(
      "TextFromParent", typeof(string), typeof(TestUserControl), new PropertyMetadata()); 
    } 
} 
012 3,516,

프로그램이 작동 바인딩 TextBlock에 의해 빈 다음에 다음과 같은 실행, 첫 번째 텍스트 다음과 같습니다 enter image description here

답변

2

UserControl을 실제로 부모 요소에서 DataContext를 상속한다. 그러나 MainWindow 인스턴스이기 때문에 해당 DataContext에 아무런 TextFromParent 속성이 없습니다.

UserControl의 XAML에서 바인딩은 현재 DataContext 중 하나가 아닌 UserControl 자체의 속성에 바인딩되어 있다고 가정합니다. 따라서 그것은 소스 객체로 UserControl을 인스턴스를 사용해야합니다 : 그것의 DataContext 값이 컨트롤의 부모 요소에서 상속되는 것을 방지하기 때문에 자신에게 해당 UserControl의 DataContext를 설정

<TextBlock Text="{Binding TextFromParent, 
        RelativeSource={RelativeSource AncestorType=UserControl}}" /> 

이 옵션을 선택하지 않습니다.

<UserControl ...> 
    <Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"> 
     <TextBlock Text="{Binding TextFromParent}" /> 
    </Grid> 
</UserControl> 
:

당신은 그러나 잠재적으로 많은 바인딩에 RelativeSource 설정을 방지하기 위해 해당 UserControl의 XAML의 루트 요소의 DataContext를 설정할 수있다