我有一个带有数据网格的WPF应用程序,用户将在其中输入文件名.我希望他们能够通过双击直接输入文件名,或者单击浏览按钮启动打开的文件对话框.

下面是XAML:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="450" Width="800">
    <DataGrid Name="TheDataGrid" 
              ItemsSource="{Binding Inputs}" 
              AutoGenerateColumns="False" 
              CanUserAddRows="True">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Filename" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <Button DockPanel.Dock="Right" Content="Browse" Click="BrowseButton_Click" />
                            <TextBlock Text="{Binding Filename}" />
                        </DockPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <Button DockPanel.Dock="Right" Content="Browse" Click="BrowseButton_Click" />
                            <TextBox Text="{Binding Filename}" />
                        </DockPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Window>

代码是这样的:

public partial class MainWindow : Window
{
    public ObservableCollection<Input> Inputs { get; set; } = new ObservableCollection<Input>();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog ofd = new OpenFileDialog();
        if (!ofd.ShowDialog().Value)
            return;
        if (((Button)sender).DataContext is Input i)
            i.Filename = ofd.FileName;
        else
        {
            // what to do here?
        }
    }
}

public class Input : INotifyPropertyChanged
{
    private string filename;

    public string Filename
    {
        get { return filename; }
        set
        {
            filename = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Filename"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

我的问题是:

  1. 当用户在新行上单击Browse按钮时,DataContext不是类型Input,而是DataGrid.NewItemPlaceholder,所以我没有什么可以设置的文件名.我try 直接修改TextBlock Text,这很管用,但它不提交新行,即使在手动发出该命令时也是如此.
  2. 当用户双击手动输入文件名时,它会进入编辑模式,但随后似乎需要再点击一次才能真正接受输入.有没有办法避免这种情况,让这种行为更像DataGridTextColumn分?

推荐答案

一天后,回到这个问题上,看看EldHasp的答案(并意识到困难的部分是添加新的行),现在解决方案似乎显而易见得令人痛苦:

private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog();
    if (!ofd.ShowDialog().Value)
        return;
    if (!(((Button)sender).DataContext is Input i))
        Inputs.Add(new Input() { Filename = ofd.FileName });
    else
        i.Filename = ofd.FileName;
}

DataContext不是Input时,即它是一个新行,您只需创建一个新行(设置适当的属性)并将其添加到绑定的集合中.

Csharp相关问答推荐

当打印一行x个项目时,如何打印最后一行项目?

C#类主构造函数中的调试参数

CS0103 dlibdotnet和www.example.com facerect不在上下文中

如何在C#中删除一个特殊字符,如"使用Regex"

MongoDB.NET-将数据绑定到模型类,但无法读取整数值

如何忽略API JSON响应中的空字符串?

如何将ASP.NET Core 2.1(在.NET框架上运行)更新到较新的版本?

使用可信第三方的Iext8.Net pdf签名

如何解决提交按钮后 Select 选项错误空参照异常

反序列化私有成员

如何让两个.NET版本不兼容的项目对话?

WPF DataGrid文件名列,允许直接输入文本或通过对话框按键浏览

当我try 在与XAMP的MySQL服务器连接的ASP.NET核心应用程序中添加迁移时出现错误

是否可以在Entity Framework Core中使用只读 struct 作为拥有实体?

VS代码扩展无法在新版本扩展C#中运行从v2.10.28开始

如何设置WinForms按钮焦点,使其看起来像是被Tab键插入其中?

如何在特定时间间隔运行多个后台任务?

除非首先访问使用的终结点,否则本地API上的终结点不起作用

S,在.NET核心控制台应用程序中,AddScope和AddSingleton有什么不同?

将两个JSON文件与覆盖值的主文件合并