我创建了一个简单的可重复使用控件来浏览文件。
然后我创建了一个模型并实现了OnPropertyChanged,并在MainWindow中使用了该控件。
当我点击UserControl中的“浏览”按钮时,依赖属性“FilePath”被正确设置(文本框也获取了路径字符串),但模型似乎没有起作用。
额外信息:如果我使用普通文本框而不是UserControl并执行...
这是我在使用INotifyPropertyChanged时所采用的模型:
这是我如何使用两个控件的方法(两个示例都无法正常工作):
然后,DependencyProperty 可以像这样(请注意 BindsTwoWayByDefault):
然后我创建了一个模型并实现了OnPropertyChanged,并在MainWindow中使用了该控件。
当我点击UserControl中的“浏览”按钮时,依赖属性“FilePath”被正确设置(文本框也获取了路径字符串),但模型似乎没有起作用。
额外信息:如果我使用普通文本框而不是UserControl并执行...
<TextBox Text="{Binding InputFile}"/>
当我在框中输入内容时,模型更新正确。
如果我手动在用户控件中输入东西(而不是通过浏览按钮填充),它仍然无法工作。
这是 UserControl 的代码,属性在控件内部正确设置:
public partial class FileBrowserTextBox : UserControl
{
public FileBrowserTextBox()
{
InitializeComponent();
}
// FilePath
public static readonly DependencyProperty FilePathProperty =
DependencyProperty.Register("FilePath", typeof(string), typeof(FileBrowserTextBox), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFilePathPropertyChanged)));
public string FilePath
{
get { return (string)GetValue(FilePathProperty); }
set { SetValue(FilePathProperty, value); }
}
static void OnFilePathPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var obj = o as FileBrowserTextBox;
if (obj == null)
return;
}
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
// Create OpenFileDialog
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Set filter for file extension and default file extension
dlg.DefaultExt = ".txt";
dlg.Filter = "TXT Files (*.txt)|*.txt|All Files (*.*)|*.*";
// Display OpenFileDialog by calling ShowDialog method
Nullable<bool> result = dlg.ShowDialog();
// Get the selected file name and display in a TextBox
if (result == true)
{
// Open document
string filename = dlg.FileName;
FilePath = filename; // this works and updates the textbox
}
}
}
以下是XAML代码片段:
<UserControl x:Class="DrumMapConverter.FileBrowserTextBox">
...
<Button Content=" ... " Click="BrowseButton_Click"/>
<TextBox Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath}"/>
...
</UserControl>
这是我在使用INotifyPropertyChanged时所采用的模型:
public class DrumMapConverterDataModel :INotifyPropertyChanged
{
public string InputFile
{
get { return inputFile; }
set
{
inputFile = value;
OnPropertyChanged("InputFile");
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private string inputFile;
}
这是MainWindow类
public partial class MainWindow : Window
{
private DrumMapConverterDataModel model;
public MainWindow()
{
InitializeComponent();
model = new DrumMapConverterDataModel();
DataContext = model;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MessageBox.Show(model.InputFile); // if i break here the model has no data changed (InputFile is null)
}
}
这是我如何使用两个控件的方法(两个示例都无法正常工作):
<cust:FileBrowserTextBox Label="Input File" FilePath="{Binding InputFile}"/>
<cust:FileBrowserTextBox Label="Input File" FilePath="{Binding Path=InputFile, Mode=TwoWay,
RelativeSource={RelativeSource FindAncestor,
AncestorType=Window}}"/>
非常感谢您的帮助。
更新和解决方案:
如@AnatoliyNikolaev所建议(感谢他对UpdareSourceTrigger的解释)和@Karuppasamy在用户控件中的建议,可以像这样完成(明确使用UpdateSourceTrigger,因为它是一个文本框):
<TextBox Grid.Column="2" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath, UpdateSourceTrigger=PropertyChanged}"/>
然后,DependencyProperty 可以像这样(请注意 BindsTwoWayByDefault):
public static readonly DependencyProperty FilePathProperty =
DependencyProperty.Register("FilePath", typeof(string), typeof(FileBrowserTextBox), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFilePathPropertyChanged)) { BindsTwoWayByDefault = true });
最后在主窗口中,我可以简单地编写以下代码:
<cust:FileBrowserTextBox FilePath="{Binding Path=InputFile}" />