C# OpenFiledialog 비 모드 가능성
-
20-08-2019 - |
문제
비 모달 .NET OpenFileDialog를 만들거나 가질 수 있습니까? 나는 메인 대화 상자에 UI 요소가 있으며 사용자가 항상 누르기 위해 사용할 수 있어야합니다.
해결책
아니, OpenFiledialog 그리고 SaveFiledialog 둘 다 파생되었습니다 Filedialog, 이것은 본질적으로 모달이므로 (내가 아는 한), 그들 중 하나의 비 모달 버전을 만들 수있는 방법은 없습니다.
다른 팁
스레드를 생성하고 스레드가 OpenFileDialog를 호스트하게 할 수 있습니다. 예제 코드에는 모든 종류의 동기화가 부족하지만 작동합니다.
public partial class Form1 : Form
{
OFDThread ofdThread;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ofdThread = new OFDThread();
ofdThread.Show();
}
}
public class OFDThread
{
private Thread t;
private DialogResult result;
public OFDThread()
{
t = new Thread(new ParameterizedThreadStart(ShowOFD));
t.SetApartmentState(ApartmentState.STA);
}
public DialogResult DialogResult { get { return this.result; } }
public void Show()
{
t.Start(this);
}
private void ShowOFD(object o)
{
OpenFileDialog ofd = new OpenFileDialog();
result = ofd.ShowDialog();
}
}
이 코드를 사용하면 UI 스레드에서 이벤트를 발사하기 위해 무언가를 추가 할 수 있습니다 (호출에주의를 기울여야합니다!). 대화 상자 결과에 액세스 할 수 있습니다
DialogResult a = ofdThread.DialogResult
UI 스레드에서.
나는 조금 늦었다는 것을 알고 있지만, 당신은 경계가없고, 투명하거나, 디스플레이 경계 외부에 새로운 형태를 만들고, 파일 대화 상자가 해당 창을 모드 할 수 있습니다.
그것은 오래된 게시물이지만, 나는 여기에 제시하고 싶은 결과에 2 일을 보냅니다 ( "컨텍스트"와 함께 완료하지만 단순화 된 코드) @joshua의 답변은 저를 위해 작동했습니다 (마침내 .configureawait (true)에 충실 할 때 마침내. , 첫 번째 코드 샘플 참조). 아마도 MSDN의 긴 기사를 기반으로 적은 줄을 쓸 수 있었을 것입니다. 스레딩 모델 여전히 다시 한 번 읽어야합니다.
내 컨텍스트는 WPF (기본 MVVM)이며 (Datagrid의) .CSV 백업을 작성하려면 파일을 선택해야합니다. (멤버) 기능이 필요합니다 ChooseFileFromExtension()
비 차단 제출물로 비동기식을하십시오
class MainWindowExportToExcelCSV : ICommand
{
...
public async void Execute(object parameter)
{
var usr_ctrl = parameter as UserControl;
MyFileDialog fd = new MyFileDialog();
const bool WhenIComeBackIStillNeedToAccessUIObjectAndThusINeedToRetrieveMyOriginalUIContext = true;
string filename = await fd.ChooseFileFromExtension("CSV files (*.csv)|*.csv|All files (*.*)|*.*").ConfigureAwait(
WhenIComeBackIStillNeedToAccessUIObjectAndThusINeedToRetrieveMyOriginalUIContext);
Visual visual = (Visual)usr_ctrl.Content;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
//look for datagrid element
}
}
}
그리고 myFiledialog 클래스의 코드
using Microsoft.Win32;
...
class MyFileDialog
{
//https://msdn.microsoft.com/en-us/library/ms741870(v=vs.110).aspx
//Article on Threading Model
private delegate void OneArgStrDelegate(string str);
private void MyExternalDialog(string extensions)
{
SaveFileDialog fd = new SaveFileDialog();
fd.Filter = extensions;
fd.ShowDialog();
tcs.SetResult(fd.FileName);
}
private TaskCompletionSource<string> tcs;
public Task<string> ChooseFileFromExtension(string file_ext)
{
//Cf Puppet Task in Async in C#5.0 by Alex Davies
tcs = new TaskCompletionSource<string>();
OneArgStrDelegate fetcher = new OneArgStrDelegate(this.MyExternalDialog);
fetcher.BeginInvoke(file_ext, null, null);
return tcs.Task;
}
}
그만큼 fetcher.BeginInvoke()
(비동기 적으로) 시작합니다 SaveFileDialog
ShowDialog()
기본 UI 스레드 / 창 (... ++)이 간단한 직접 호출과 마찬가지로 차단되거나 비활성화되지 않도록 다른 스레드에서 ShowDialog()
. TaskCompletionSource<string> tcs
WPF UI 객체가 아니므로 다른 "단일"스레드에 의한 액세스는 괜찮습니다.
여전히 더 공부 해야하는 분야입니다. 주제에 대한 "궁극적 인"문서/책이 없다고 생각합니다 (아마도 Stephen Cleary의 One과 같은 책을 다시 한 번 살펴보아야합니다). 이 코드는 적어도 주제를 다루면 개선되어야합니다. C-SHARP-ASYNCHRONOUS-CALL-WITHOUT-ENDINVOKE
네임 스페이스 Microsoft.win32의 Filedialog와 함께 작동합니다