Dispatcher здесь не помогает, потому что, когда окно создается в другом потоке, оно не содержится в коллекции Application.Windows
, а в коллекции, которая почему-то не отображается (называется NonAppWindowsInternal). Вскоре нет официального способа сделать это. Конечно, вы можете использовать размышления на свой страх и риск.
Но если окно находится на UI потоке, и вы просто хотите вызвать функцию из другого потока, то вы можете использовать что-то вроде этого
Application.Current.Dispatcher.Invoke(() => IsWindowOpen<...>(...))
или лучше изменить вспомогательный метод быть
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return Application.Current.Dispatcher.Invoke(() => string.IsNullOrEmpty(name)
? Application.Current.Windows.OfType<T>().Any()
: Application.Current.Windows.OfType<T>().Any(w => w.Name.Equals(name)));
}
EDIT Вот то, что работает в настоящее время, но может измениться в будущем, так как уже упоминалось выше, использовать его на свой страх и риск
public static class WindowUtils
{
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return FindWindow<T>(name) != null;
}
public static T FindWindow<T>(string name = "") where T : Window
{
return FindWindow<T>(WindowsInternal, name) ?? FindWindow<T>(NonAppWindowsInternal, name);
}
private static T FindWindow<T>(Func<Application, WindowCollection> windowListAccessor, string name = "") where T : Window
{
bool matchName = !string.IsNullOrEmpty(name);
var windowList = windowListAccessor(Application.Current);
for (int i = windowList.Count - 1; i >= 0; i--)
{
var window = windowList[i] as T;
if (window != null && (!matchName || window.Name == name)) return window;
}
return null;
}
private static readonly Func<Application, WindowCollection> WindowsInternal = GetWindowCollectionAccessor("WindowsInternal");
private static readonly Func<Application, WindowCollection> NonAppWindowsInternal = GetWindowCollectionAccessor("NonAppWindowsInternal");
private static Func<Application, WindowCollection> GetWindowCollectionAccessor(string propertyName)
{
var property = typeof(Application).GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
return (Func<Application, WindowCollection>)Delegate.CreateDelegate(
typeof(Func<Application, WindowCollection>), property.GetMethod);
}
}
Что исключение вы получаете? – Sievajet
Окно происходит из DispatcherObject, который содержит ссылку на Диспетчер, связанный с потоком, в котором было создано окно. что-то вроде: _window.Dispatcher, BeginInvoke (() => ,,,,,); –
@Sievajet окно wpf было создано в другом потоке, поэтому я получаю исключение, что я не могу получить к нему доступ из другого потока. По крайней мере, с этим методом. Я хотел бы назвать это из основного потока. – konrad