我创建了一个小的文件浏览器控件:
<UserControl x:Class="Test.UserControls.FileBrowserControl" 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="44" d:DesignWidth="461" Name="Control"> <Grid Margin="3"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <TextBox Margin="3" Text="{Binding SelectedFile}" IsReadOnly="True" TextWrapping="Wrap" /> <Button HorizontalAlignment="Right" Margin="3" Width="100" Content="Browse" Grid.Column="1" Command="{Binding BrowseCommand}" /> </Grid> </UserControl>
后面有以下代码:
public partial class FileBrowserControl : UserControl { public ICommand BrowseCommand { get; set; } //The dependency property public static DependencyProperty SelectedFileProperty = DependencyProperty.Register("SelectedFile", typeof(string),typeof(FileBrowserControl), new PropertyMetadata(String.Empty)); public string SelectedFile { get{ return (string)GetValue(SelectedFileProperty);} set{ SetValue(SelectedFileProperty, value);}} //For my first test, this is a static string public string Filter { get; set; } public FileBrowserControl() { InitializeComponent(); BrowseCommand = new RelayCommand(Browse); Control.DataContext = this; } private void Browse() { SaveFileDialog dialog = new SaveFileDialog(); if (Filter != null) { dialog.Filter = Filter; } if (dialog.ShowDialog() == true) { SelectedFile = dialog.FileName; } } }
我这样使用它:
<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" Filter="XSLT File (*.xsl)|*.xsl|All Files (*.*)|*.*"/>
(SelectedFile是使用此控件的用户控件的ViewModel的属性)
当前的问题是,当我单击“浏览”时,usercontrol中的文本框正在正确更新,但是未设置viewmodel父控件的SelectedFile属性(未调用set属性)。
如果将绑定的模式设置为TwoWay,则会出现以下异常:
An unhandled exception of type 'System.StackOverflowException' occurred in Unknown Module.
那我做错了什么?
主要问题是您在其构造函数中将UserControl的DataContext设置为其自身:
DataContext = this;
您不应该这样做,因为它会中断任何基于DataContext的绑定,例如,到继承的DataContext值中的视图模型实例的绑定。
相反,您可以像这样在UserControl的XAML中更改绑定:
<TextBox Text="{Binding SelectedFile, RelativeSource={RelativeSource AncestorType=UserControl}}" />
现在,当您使用UserControl并编写类似
<userControls:FileBrowserControl SelectedFile="{Binding SelectedFile}" />
SelectedFile属性绑定到视图模型中的SelectedFile属性,该属性应该在从父控件继承的DataContext中。