我正在使用 DataTemplate 作为具有属性文件地址的类型。我需要使用TextBox
创建Button
,这将打开OpenFileDialog
,然后将选定的文件地址插入TextBox
。
我想知道创建TextBox
和Button
的最佳方式是什么,它会显示OpenFileDialog
。并且不要忘记这是DataTemplate
因此我知道DataTemplate
没有任何代码隐藏。
我在想UserControl
,但如果那是最好的方式,我不会这样做吗?
谢谢大家
答案 0 :(得分:2)
UserControl是一个完全可以接受的解决方案,但我更可能使用1)自定义控件,或2)RoutedUICommand。
构建自定义控件
创建一个从TextBox派生的简单控件:
public class TextBoxWithFileDialog : TextBox
{
static TextBoxWithFileDialog()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxWithFileDialog), new FrameworkPropertyMetadata(typeof(TextBoxWithFileDialog)));
CommandManager.RegisterClassCommandBinding(typeof(TextBoxWithFileDialog), new CommandBinding(
ApplicationCommands.Open,
(obj, e) => { e.Handled = true; ((TextBoxWithFileDialog)obj).ShowFileOpenDialog(); },
(obj, e) => { e.CanExecute = true; }));
}
void ShowFileOpenDialog()
{
var dialog = new Microsoft.Win32.OpenFileDialog
{
DefaultExt = ".txt"
};
if(dialog.ShowDialog()==true)
Text = dialog.FileName;
}
}
然后在themes / Generic.xaml或其中包含的资源字典中添加包含适当ControlTemplate的样式:
<Style TargetType="{x:Type TextBoxWithFileDialog}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxWithFileDialog}">
<DockPanel>
<Button Content="..." Command="Open" DockPanel.Dock="Right" />
<!-- copy original TextBox control template contents here -->
</DockPanel>
... close rest of tags ...
您可以使用Expression Blend或Reflector / BamlViewer复制TextBox现有的ControlTemplate。
对于我自己的项目,我更愿意将这样的解决方案添加到我的控件库中,以便我可以在任何我想要的地方使用它。但是,如果您只打算使用一次,这可能会有点过分。在那种情况下,我只会:
使用RoutedUICommand
public partial class MyWindow : Window
{
public Window()
{
InitializeComponent();
...
CommandManager.RegisterClassCommandBinding(typeof(TextBoxWithFileDialog), new CommandBinding(
ApplicationCommands.Open,
(obj, e) =>
{
e.Handled = true;
((MyWindow)obj).ShowFileOpenDialog((TextBox)e.Parameter);
},
(obj, e) => { e.CanExecute = true; }));
}
void ShowFileOpenDialog(TextBox textBox)
{
var dialog = new Microsoft.Win32.OpenFileDialog
{
DefaultExt = ".txt"
};
if(dialog.ShowDialog()==true)
textBox.Text = dialog.FileName;
}
}
这不需要样式或其他类。只需命名文本框,然后将按钮引用文本框作为其命令参数:
<TextBox x:Name="Whatever" ... />
<Button Content="..." Command="Open" CommandParameter="{Binding ElementName=Whatever}" />
这就是它的全部。不幸的是,它只能在一个窗口中工作,并将其放在其他地方需要剪切和粘贴。这就是我更喜欢自定义控件的原因。
注意强>
如果您已在应用程序的其他位置使用ApplicationCommands.Open,则可以选择其他命令,或创建自己的命令:
public static readonly RoutedUICommand MyCommand = new RoutedUICommand(...)