2011-01-19 132 views
3

我想將一個值從一個窗口綁定到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 
} 

我知道樹的作品, BEC如果我只是把樹放在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" />  

另一種可能性是設置用戶控件此引用到DataContext。這應該也有幫助。

+0

我已更新帖子。我一直在將每個xaml類的DataContext設置爲一個自定義對象。我之所以留下這個印象,是因爲FileSystemTree在FileSystemBrowser中聲明瞭一個綁定,只要FileSystemBrowser中分配的DataContext的屬性被更新,它就會觸發對FileSystemTree的更新。 – Xaiter 2011-01-20 13:40:24