开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜