2011-01-19 191 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