문제

인 방법을 알고 싶 전문가된 이 개발자 처리 openfile 대화에서 WPF.

내가 정말 원하지 않 이를 위해서 뷰 모델(는'검색'참조를 통해 DelegateCommand)

void Browse(object param)
{
    //Add code here
    OpenFileDialog d = new OpenFileDialog();

    if (d.ShowDialog() == true)
    {
        //Do stuff
    }
}

기 때문에 믿는가에 대하여된 이 방법입니다.

나는 무엇을 할까?

도움이 되었습니까?

해결책

여기서 가장 좋은 방법은 서비스를 사용하는 것입니다.

서비스는 중앙 서비스 저장소, 종종 IOC 컨테이너에서 액세스하는 클래스 일뿐입니다. 그런 다음 서비스는 OpenFiledialog처럼 필요한 것을 구현합니다.

그래서, 당신이 있다고 가정합니다 IFileDialogService Unity 컨테이너에서는 할 수 있습니다 ...

void Browse(object param)
{
    var fileDialogService = container.Resolve<IFileDialogService>();

    string path = fileDialogService.OpenFileDialog();

    if (!string.IsNullOrEmpty(path))
    {
        //Do stuff
    }
}

다른 팁

나는 답 중 하나에 대해 언급하고 싶었지만 아아, 내 평판은 그렇게 높지 않습니다.

OpenFileDialog ()와 같은 호출은 뷰 모델에서보기 (대화 상자)를 의미하기 때문에 MVVM 패턴을 위반합니다. 보기 모델은 getFileName ()과 같은 것을 호출 할 수 있지만 (즉, 단순한 바인딩이 충분하지 않은 경우) 파일 이름을 얻는 방법은 신경 쓰지 않아야합니다.

예를 들어 뷰 모델의 생성자로 전달하거나 종속성 주입을 통해 해결할 수있는 서비스를 사용합니다. 예를 들어

public interface IOpenFileService
{
    string FileName { get; }
    bool OpenFileDialog()
}

그리고 후드 아래에서 OpenFiledialog를 사용하여 그것을 구현하는 클래스. ViewModel에서는 인터페이스 만 사용하므로 필요한 경우 조롱/교체 할 수 있습니다.

뷰 모델 열리지 않아야 하는 대화 상자에 나도 모르는 존재이다.면 VM 에 보관되어 있는 별도의 DLL,프로젝트가 없어야에 대한 참조 PresentationFramework.

내가 사용하는 데 사용할 수 있는 도우미 클래스에서보기에 대한 일반적인 메시지가 나타납니다.

도우미 클래스를 노출을 명령하지 않는(이벤트)에 창 바인딩에서 XAML.이 의미의 사용 RelayCommand 에서 보기입니다.도우미 클래스는 DepencyObject 그래서 그것은 바인딩 할 수 있습을 볼 모델입니다.

class DialogHelper : DependencyObject
{
    public ViewModel ViewModel
    {
        get { return (ViewModel)GetValue(ViewModelProperty); }
        set { SetValue(ViewModelProperty, value); }
    }

    public static readonly DependencyProperty ViewModelProperty =
        DependencyProperty.Register("ViewModel", typeof(ViewModel), typeof(DialogHelper),
        new UIPropertyMetadata(new PropertyChangedCallback(ViewModelProperty_Changed)));

    private static void ViewModelProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (ViewModelProperty != null)
        {
            Binding myBinding = new Binding("FileName");
            myBinding.Source = e.NewValue;
            myBinding.Mode = BindingMode.OneWayToSource;
            BindingOperations.SetBinding(d, FileNameProperty, myBinding);
        }
    }

    private string FileName
    {
        get { return (string)GetValue(FileNameProperty); }
        set { SetValue(FileNameProperty, value); }
    }

    private static readonly DependencyProperty FileNameProperty =
        DependencyProperty.Register("FileName", typeof(string), typeof(DialogHelper),
        new UIPropertyMetadata(new PropertyChangedCallback(FileNameProperty_Changed)));

    private static void FileNameProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Debug.WriteLine("DialogHelper.FileName = {0}", e.NewValue);
    }

    public ICommand OpenFile { get; private set; }

    public DialogHelper()
    {
        OpenFile = new RelayCommand(OpenFileAction);
    }

    private void OpenFileAction(object obj)
    {
        OpenFileDialog dlg = new OpenFileDialog();

        if (dlg.ShowDialog() == true)
        {
            FileName = dlg.FileName;
        }
    }
}

도우미 클래스 요구에 대한 참조를 시점 인스턴스입니다.보 자원 사전입니다.후 건축,뷰 모델 속성을 설정(동일한 선 XAML).이 때에 파일이름 속에서 도우미 클래스 바운드 파일 속에 넣는 모델입니다.

<Window x:Class="DialogExperiment.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DialogExperiment"
        xmlns:vm="clr-namespace:DialogExperimentVM;assembly=DialogExperimentVM"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <vm:ViewModel x:Key="viewModel" />
        <local:DialogHelper x:Key="helper" ViewModel="{StaticResource viewModel}"/>
    </Window.Resources>
    <DockPanel DataContext="{StaticResource viewModel}">
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="File">
                <MenuItem Header="Open" Command="{Binding Source={StaticResource helper}, Path=OpenFile}" />
            </MenuItem>
        </Menu>
    </DockPanel>
</Window>

서비스를 갖는 것은 ViewModel에서보기를 열는 것과 같습니다. 나는 의존성 속성을 보유하고 있으며, 재산의 갈대지에 Filedialog를 열고 경로를 읽고, 속성을 업데이트하고 결과적으로 VM의 바운드 속성을 업데이트합니다.

나는 이런 식으로 나를 위해 그것을 해결했다 :

  • ~ 안에 뷰 모델 인터페이스를 정의하고 ViewModel에서 작업했습니다.
  • ~ 안에 보다 이 인터페이스를 구현했습니다.

Commandimpl은 아래 코드에서 구현되지 않습니다.

ViewModel :

namespace ViewModels.Interfaces
{
    using System.Collections.Generic;
    public interface IDialogWindow
    {
        List<string> ExecuteFileDialog(object owner, string extFilter);
    }
}

namespace ViewModels
{
    using ViewModels.Interfaces;
    public class MyViewModel
    {
        public ICommand DoSomeThingCmd { get; } = new CommandImpl((dialogType) =>
        {
            var dlgObj = Activator.CreateInstance(dialogType) as IDialogWindow;
            var fileNames = dlgObj?.ExecuteFileDialog(null, "*.txt");
            //Do something with fileNames..
        });
    }
}

보다:

namespace Views
{
    using ViewModels.Interfaces;
    using Microsoft.Win32;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;

    public class OpenFilesDialog : IDialogWindow
    {
        public List<string> ExecuteFileDialog(object owner, string extFilter)
        {
            var fd = new OpenFileDialog();
            fd.Multiselect = true;
            if (!string.IsNullOrWhiteSpace(extFilter))
            {
                fd.Filter = extFilter;
            }
            fd.ShowDialog(owner as Window);

            return fd.FileNames.ToList();
        }
    }
}

XAML :

<Window

    xmlns:views="clr-namespace:Views"
    xmlns:viewModels="clr-namespace:ViewModels"
>    
    <Window.DataContext>
        <viewModels:MyViewModel/>
    </Window.DataContext>

    <Grid>
        <Button Content = "Open files.." Command="{Binding DoSomeThingCmd}" CommandParameter="{x:Type views:OpenFilesDialog}"/>
    </Grid>
</Window>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top