OpenFileDialog with WPF in M-V-VM pattern
I need to use the OpenFileDialog to select a fil开发者_StackOverflow社区e, but I can't use any of the MVVM-centric toolkits like Galgasoft that allow me to do this without violating the MVVM pattern.
How else can I achieve this?
Sure, here's an example of some code I use to read Excel files. It goes in a ViewModel
and gets called from a 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");
}
}
You need to reference Microsoft.Win32
for the OpenFileDialog
You can create a custom control, so you can just bind a string from it to your viewmodel property.
The custom control I usually create is composed from:
- Textbox or textblock
- Button with an image as template
- String dependency property where the file path will be wrapped to
So the *.xaml file would be like this
<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>
And the *.cs file:
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;
}
}
At the end you can bind it to your view model:
<controls:customFilePicker Text="{Binding Text}"}/>
精彩评论