WPF Nested Usercontrol bindings
I'm trying to bind a value down from a Window into a UserControl inside a UserControl. But, for some reason, the inner UserControl never even attempts to bind as far as I can tell.
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>
FileSystemBrowser.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
}
I know that the tree works, because if I just put the tree inside MainWindow.xaml, it's fine. But for some reason, the RootPath value from MainWindow.xam开发者_开发问答l gets bound into FileSystemBrowser and stops there. It never makes it all the way down to FileSystemTree. What am I missing?
There is to few information to be certain, but I think the problem is the DataContext that is not set. Try relative bindings, this will probably help. In FileSystemBrowser.xaml change the binding as follows:
<my:FileSystemTree x:Name="fileSystemTree1"
RootPath="{Binding Path=RootPath,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
Width="150" />
Another possibility would be to set the UserControls this-reference to the DataContext. This should also help.
精彩评论