wpf创建一个带有openfiledialog按钮的文本框

时间:2009-11-06 20:54:04

标签: wpf user-controls datatemplate

我正在使用 DataTemplate 作为具有属性文件地址的类型。我需要使用TextBox创建Button,这将打开OpenFileDialog,然后将选定的文件地址插入TextBox

我想知道创建TextBoxButton的最佳方式是什么,它会显示OpenFileDialog。并且不要忘记这是DataTemplate因此我知道DataTemplate没有任何代码隐藏。

我在想UserControl,但如果那是最好的方式,我不会这样做吗?

谢谢大家

1 个答案:

答案 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(...)