Ответ 1
Попробуйте использовать
.Owner = Window.GetWindow(this)
У меня есть приложение WPF с этими тремя типами вещей...
UserControlZack1 находится на моем WindowMain...
<Window x:Class="WindowMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProjectName"
...
Name="WindowMain">
<Grid>
...
<local:UserControlZack x:Name="UserControlZack1" ... />
...
</Grid>
</Window>
UserControlZack1 отображает окно окна WindowModal...
Partial Public Class UserControlZack ... Private Sub SomeButton_Click(...) 'instantiate the dialog box and open modally... Dim box As WindowModal = New WindowModal() box.Owner = ????? box.ShowDialog() 'process data entered by user if dialog box is accepted... If (box.DialogResult.GetValueOrDefault = True) Then _SomeVar = box.SomeVar ... End If End Sub End Class
Как установить box.Owner в нужное окно, мой исполняемый экземпляр WindowMain?
Я не могу использовать box.Owner = Me.Owner
, потому что "Владелец" не является членом "ProjectName.UserControlZack".
Я не могу использовать box.Owner = Me.Parent
, потому что он возвращает Grid, а не Window.
Я не могу использовать box.Owner = WindowMain
, потому что "WindowMain" является типом и не может использоваться как выражение.
Попробуйте использовать
.Owner = Window.GetWindow(this)
Чтобы получить окно верхнего уровня, в котором находится ваш элемент управления, если он есть:
(Window)PresentationSource.FromVisual(this).RootVisual
Чтобы получить главное окно:
Application.Current.MainWindow
MyWpfDialog dialog = new MyWpfDialog();
//remember, this is WinForms UserControl and its Handle property is
//actually IntPtr containing Win32 HWND.
new System.Windows.Interop.WindowInteropHelper(dialog).Owner = this.Handle;
dialog.ShowDialog();
Обновление, чтобы попытаться помочь Грегу в комментариях. Команда работает в главном меню Windows, в элементе управления пользователя и в контекстном меню пользовательского элемента управления.
Я бы сделал это с помощью команд. Так что у класса Commands.cs что-то вроде:
public static class Commands
{
public static RoutedUICommand TestShowDialogCommand = new RoutedUICommand("Test command", "TestShowDialog", typeof(Commands));
}
Зарегистрируйте их в своем главном окне: (вам не нужно, чтобы строка canshow по умолчанию была равна true)
public Window1()
{
InitializeComponent();
CommandManager.RegisterClassCommandBinding(typeof(System.Windows.Controls.Control),
new CommandBinding(Commands.TestShowDialogCommand, ShowDialogCommand, CanShowDialogCommand));
}
private void ShowDialogCommand(object sender, ExecutedRoutedEventArgs e)
{
var box = new Window();
box.Owner = this;
box.ShowDialog();
}
private void CanShowDialogCommand(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
Это мой xaml для главного окна:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication1="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="322">
<Grid>
<StackPanel>
<Menu>
<MenuItem Header="Test">
<MenuItem Header="ShowDialog" Command="{x:Static WpfApplication1:Commands.TestShowDialogCommand}"/>
</MenuItem>
</Menu>
<WpfApplication1:BazUserControl />
</StackPanel>
</Grid>
</Window>
Это xaml для моего пользовательского элемента управления (только по умолчанию)
<UserControl x:Class="WpfApplication1.BazUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication1="clr-namespace:WpfApplication1"
Height="300" Width="300">
<Grid>
<StackPanel>
<Button Command="{x:Static WpfApplication1:Commands.TestShowDialogCommand}" Content="ClickMe" ></Button>
<TextBox>
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="ShowDialog" Command="{x:Static WpfApplication1:Commands.TestShowDialogCommand}" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</StackPanel>
</Grid>
</UserControl>
Вы можете сделать это немного дальше и обработать команду в классе контроллера вместо этого и сделать так, чтобы бит больше MVC.
Я получил его для работы, полностью сканировав свой XAML...
box.Owner = DirectCast(DirectCast(DirectCast(Me.Parent, Grid).Parent, Grid).Parent, Window)
Но это кажется совершенно неэлегантным. Есть ли лучший способ?
Как насчет того, чтобы изменить имя окна на WindowMain1 или что-то еще, и присвоить этому владельцу?