【问题标题】:OpenFileDialog with WPF in M-V-VM pattern使用 M-V-VM 模式的 WPF 的 OpenFileDialog
【发布时间】:2011-08-18 15:11:22
【问题描述】:

我需要使用 OpenFileDialog 来选择一个文件,但我不能使用任何以 MVVM 为中心的工具包,例如 Galgasoft,它允许我在不违反 MVVM 模式的情况下执行此操作。

我还能如何做到这一点?

【问题讨论】:

标签: wpf mvvm openfiledialog


【解决方案1】:

当然,这是我用来读取 Excel 文件的一些代码示例。它进入ViewModel 并从SelectFileCommand 调用

private void SelectFile()
{
    var dlg = new OpenFileDialog();
    dlg.DefaultExt = ".xls|.xlsx";
    dlg.Filter = "Excel documents (*.xls, *.xlsx)|*.xls;*.xlsx";

    if (dlg.ShowDialog() == true)
    {
        var file = new FileInfo(dlg.FileName);
        ReadExcelFile(file.FullName);
    }
}

private void ReadExcelFile(fileName)
{
    try
    {
        using (var conn = new OleDbConnection(string.Format(@"Provider=Microsoft.Ace.OLEDB.12.0;Data Source={0};Extended Properties=Excel 8.0", fileName)))
        {
            OleDbDataAdapter da = new OleDbDataAdapter("SELECT DISTINCT [File Number] FROM [Sheet1$]", conn);
            var dt = new DataTable();
            da.Fill(dt);

            int i;
            FileContents = (from row in dt.AsEnumerable()
                            where int.TryParse(row[0].ToString(), out i)
                            select row[0]).ToList()
                            .ConvertAll<int>(p => int.Parse(p.ToString()));
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unable to read contents:\n\n" + ex.Message, "Error");
    }
}

OpenFileDialog 需要参考 Microsoft.Win32

【讨论】:

  • 我在您的解决方案中看到的一个缺点是,以这种方式显示对话框不利于您的视图模型的可测试性。因此,我更喜欢使用 stackoverflow.com/questions/1043918/open-file-dialog-mvvm/… 中提出的“IDialogService”
  • 我实际上有一个 OpenFileViewModel,你可以在其中注入如何处理文件,但我认为作为一个类的一部分会更容易阅读。
【解决方案2】:

您可以创建一个自定义控件,因此您只需将一个字符串从它绑定到您的视图模型属性。

我通常创建的自定义控件由以下组成:

  • 文本框或文本块
  • 以图像为模板的按钮
  • 文件路径将被包装到的字符串依赖属性

所以 *.xaml 文件应该是这样的

<Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>

    <TextBox Grid.Column="0" Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    <Button Grid.Column="1"
            Click="Button_Click">
        <Button.Template>
            <ControlTemplate>
                <Image Grid.Column="1" Source="../Images/carpeta.png"/>
            </ControlTemplate>                
        </Button.Template>
    </Button>

</Grid>

还有 *.cs 文件:

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(customFilePicker),
        new FrameworkPropertyMetadata(
            null,
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal));

    public string Text
    {
        get
        {
            return this.GetValue(TextProperty) as String;
        }
        set
        {
            this.SetValue(TextProperty, value);
        }
    }

    public FilePicker()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();

        if(openFileDialog.ShowDialog() == true)
        {
            this.Text = openFileDialog.FileName;
        }
    }

最后你可以将它绑定到你的视图模型:

<controls:customFilePicker Text="{Binding Text}"}/>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多