开发者

wpf create a textbox with a button for openfiledialog

I'm using a DataTemplate for a type that has a property which is the file address. I need to create a TextBox with a Button which will open an OpenFileDialog and then insert the selected file address into the TextBox.

I wanna know what's the best way for c开发者_运维问答reating the TextBox and the Button next to it which will show the OpenFileDialog. And don't forget that this is a DataTemplate so as I know I don't have any codebehind for the DataTemplate.

I was thinking about a UserControl but I don't if that's the best way or not?

Thank you all


A UserControl is a perfectly acceptable solution, but I would be more likely to use either 1) a custom control, or 2) a RoutedUICommand.

Building a Custom Control

Create a simple control derived from 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;
  }
}

then in themes/Generic.xaml or a resource dictionary included from it add a style containing an appropriate 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 ...

You can copy TextBox's existing ControlTemplate using Expression Blend or Reflector/BamlViewer).

For my own projects I would prefer to add a solution like this to my control library so I can use it anywhere I want. However this may be overkill if you're only going to use it once. In that case I would just:

Using a 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;
  }
}

This does not require a style or an additional class. Just name your textbox, and have the button refer to the textbox as its command parameter:

<TextBox x:Name="Whatever" ... />
<Button Content="..." Command="Open" CommandParameter="{Binding ElementName=Whatever}" />

That's all there is to it. Unfortunately it only works in one window, and putting it somewhere else would require cut-and-paste. That's why I prefer a custom control.

Note

If you're already using ApplicationCommands.Open elsewhere in your application, you might select a different command, or create your own:

public static readonly RoutedUICommand MyCommand = new RoutedUICommand(...)
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜