2011-01-19 6 views
3

값을 Window에서 UserControl 내부의 UserControl에 바인딩하려고합니다. 하지만, 어떤 이유로, 내부 UserControl 심지어 내가 말할 수있는만큼 바인딩하려고 시도하지 않습니다.WPF 중첩 된 사용자 정의 컨트롤

MainWindow.xaml

<Window x:Class="PdfExample.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" xmlns:my="clr-namespace:PdfExample"> 
<Grid> 
    <my:FileSystemBrowser HorizontalAlignment="Left" x:Name="fileSystemBrowser1" VerticalAlignment="Top" Height="311" Width="417" RootPath="C:\TFS\AE.Web.ezHealthQuoter.Common\1_Dev\Shared\Pdfs" /> 
</Grid> 

FileSystemBrowser.xaml

<UserControl x:Class="PdfExample.FileSystemBrowser" 
     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" 
     d:DesignHeight="300" d:DesignWidth="300" xmlns:my="clr-namespace:PdfExample"> 
<DockPanel> 
    <my:FileSystemTree x:Name="fileSystemTree1" RootPath="{Binding Path=RootPath}" Width="150" /> 
    <ListBox DockPanel.Dock="Right" /> 
</DockPanel> 

FileSystemBrows er.xaml.cs

public partial class FileSystemBrowser : UserControl 
{ 
    #region Static Members 
    static FileSystemBrowser() 
    { 
     PropertyChangedCallback rootPathChangedCallback = new PropertyChangedCallback(OnRootPathChanged); 
     PropertyMetadata metaData = new PropertyMetadata(rootPathChangedCallback); 
     RootPathProperty = DependencyProperty.Register("RootPath", typeof(string), typeof(FileSystemBrowser), metaData); 
    } 

    static DependencyProperty RootPathProperty; 

    public static void OnRootPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     (d as FileSystemBrowser).RootPath = e.NewValue as string; 
    } 
    #endregion 

    public string RootPath 
    { 
     get { return this.ViewModel.RootPath; } 
     set { this.ViewModel.RootPath = value; } 
    } 

    public FileSystemBrowserViewModel ViewModel 
    { 
     get; 
     protected set; 
    } 

    public FileSystemBrowser() 
    { 
     InitializeComponent(); 
     this.ViewModel = new FileSystemBrowserViewModel(); 
     this.DataContext = this.ViewModel; 
    } 
} 

public class FileSystemBrowserViewModel : INotifyPropertyChanged 
{ 
    private string _rootPath; 
    public string RootPath 
    { 
     get { return _rootPath; } 
     set { _rootPath = value; RaisePropertyChanged("RootPath"); } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion 
} 

FileSystemTree.xaml

<UserControl x:Class="PdfExample.FileSystemTree" 
     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" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<DockPanel> 
    <TreeView SelectedValuePath="{Binding Path=SelectedValuePath, Mode=TwoWay}" HorizontalAlignment="Stretch" Name="treeView1" VerticalAlignment="Stretch" ItemsSource="{Binding RootFolder}" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Margin="0"> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate ItemsSource="{Binding Folders}">      
       <TextBlock Text="{Binding FolderName}" /> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 
</DockPanel> 

FileSystemTree.xaml.cs

public partial class FileSystemTree : UserControl, INotifyPropertyChanged 
{ 
    #region Static Members 

    static DependencyProperty RootPathProperty; 

    static FileSystemTree() 
    { 
     PropertyChangedCallback rootPathChangedCallback = new PropertyChangedCallback(OnRootPathChanged); 
     PropertyMetadata metaData = new PropertyMetadata(rootPathChangedCallback); 
     RootPathProperty = DependencyProperty.Register("RootPath", typeof(string), typeof(FileSystemTree), metaData); 
    } 

    public static void OnRootPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     (d as FileSystemTree).RootPath = e.NewValue as string; 
    } 

    #endregion 

    public string RootPath 
    { 
     get { return this.ViewModel.RootPath; } 
     set { this.ViewModel.RootPath = value; } 
    } 

    public FileSystemTreeViewModel ViewModel 
    { 
     get; 
     protected set; 
    } 

    public FileSystemTree() 
    {    
     InitializeComponent(); 
     this.ViewModel = new FileSystemTreeViewModel(); 
     this.DataContext = this.ViewModel; 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion 
} 

public class FileSystemTreeViewModel : INotifyPropertyChanged 
{ 
    public IFolder[] RootFolder 
    { 
     get 
     { 
      if (RootPath != null) 
       return new IFolder[] { new FileSystemFolder(RootPath) }; 

      return null; 
     } 
    } 

    private string _rootPath; 
    public string RootPath 
    { 
     get { return _rootPath; } 
     set 
     { 
      _rootPath = value; 
      RaisePropertyChanged("RootPath"); 
      RaisePropertyChanged("RootFolder"); 
     } 
    } 

    private string _selectedValuePath; 
    protected string SelectedValuePath 
    { 
     get { return _selectedValuePath; } 
     set { _selectedValuePath = value; } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion 
} 

나는 그 나무 작동하는 벡 ause를 MainWindow.xaml 안에두면 괜찮습니다. 그러나 어떤 이유로 MainWindow.xaml의 RootPath 값은 FileSystemBrowser에 바인딩되어 거기에서 멈 춥니 다. 결코 FileSystemTree로 내려 가지 않습니다. 내가 뭘 놓치고 있니?

답변

2

확신할만한 정보가 있지만 문제는 설정되지 않은 DataContext라고 생각합니다. 상대 바인딩을 시도하면 도움이 될 것입니다. 다음 FileSystemBrowser.xaml에서 바인딩을 변경

<my:FileSystemTree x:Name="fileSystemTree1" 
    RootPath="{Binding Path=RootPath,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" 
    Width="150" />  

다른 가능성이 된 UserControls DataContext를이 참조를 설정하는 것이다. 이것은 또한 도움이됩니다.

+0

게시물을 업데이트했습니다. 각 xaml 클래스의 DataContext를 사용자 지정 개체로 설정했습니다. FileSystemBreeser에 할당 된 DataContext의 속성이 업데이트 될 때마다 FileSystemBreeser에서 바인딩을 사용하여 FileSystemTree가 선언 되었기 때문에 인상적이었습니다. FileSystemBreeser에 업데이트가 트리거됩니다. – Xaiter

+0

이 업데이트를 전파 할 바인딩이 없습니다. 더욱이, 생성자에서'DataContext' 하드 세트로 당신은 당신이 찾고있는 것을 얻지 못할 것입니다. – user7116

+0

컨트롤 당 DataContext를 할당하지 않으면 기본적으로 모두 Window 수준에서 할당 된 값으로 설정됩니다. 즉, 모든 중첩 컨트롤에서 값에 대해 기대하는 Window를 완벽하게 인식하는 DataContext 개체를 만들어야한다는 의미입니다. 이는 특히 중첩 된 사용자 정의 컨트롤에서 양방향 바인딩을 사용하는 경우 제어 재사용 지점을 무력화시키는 것으로 보입니다. WPF 컨트롤을 구성하는 방법에 대한 근본적인 설명이 빠졌습니까? – Xaiter

관련 문제