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

发布于 2024-08-10 02:41:13 字数 445 浏览 5 评论 0原文

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

我想知道创建 TextBox 及其旁边的 Button 的最佳方法是什么,它将显示 OpenFileDialog。并且不要忘记这是一个 DataTemplate,因此据我所知,我没有任何 DataTemplate 的代码隐藏。

我正在考虑 UserControl 但我不知道这是否是最好的方法?

谢谢大家

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 creating 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故人的歌 2024-08-17 02:41:13

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

然后在 theme/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 复制 TextBox 的现有 ControlTemplate或反射器/BamlViewer)。

对于我自己的项目,我更愿意将这样的解决方案添加到我的控件库中,这样我就可以在任何我想要的地方使用它。然而,如果您只使用一次,这可能有点过头了。在这种情况下,我只需:

使用 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(...)

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(...)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文