Вопрос или проблема
У меня есть простое окно WPF с пользовательской заголовочной панелью, но метод DragMove()
работает только на TextBlock
. Если я пытаюсь перетянуть окно по пустому месту рядом с заголовком, ничего не происходит…
<Window x:Class="WPFApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFApplication"
mc:Ignorable="d"
ResizeMode="CanMinimize"
WindowStartupLocation="CenterScreen"
WindowStyle="None" AllowsTransparency="True" Background="#FFFFFFFF"
Title="WPF Application" Height="460" Width="1040">
<Grid>
<!-- Пользовательская заголовочная панель -->
<Border Height="40" VerticalAlignment="Top"
x:Name="TitleBar"
Panel.ZIndex="1">
<DockPanel>
<!-- Имя и иконка приложения -->
<StackPanel Margin="10,0,0,0" Orientation="Horizontal" DockPanel.Dock="Left">
<TextBlock Text="WPF Application"
VerticalAlignment="Center"
FontSize="16"/>
</StackPanel>
<!-- Кнопки управления окном -->
<StackPanel Orientation="Horizontal" DockPanel.Dock="Right" HorizontalAlignment="Right">
<!-- Кнопка сворачивания -->
<Button Width="40"
Content="_"
Click="MinimizeWindow"
Background="Transparent"/>
<!-- Кнопка разворачивания/восстановления -->
<Button Width="40"
Content="▢"
Click="MaximizeRestoreWindow"
Background="Transparent"/>
<!-- Кнопка закрытия -->
<Button Width="40"
Content="X"
Click="CloseWindow"
Background="Transparent"/>
</StackPanel>
</DockPanel>
</Border>
<TextBlock Text="test" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TitleBar.MouseDown += (sender, e) =>
{
if (e.ButtonState == System.Windows.Input.MouseButtonState.Pressed)
{
// Вызвать DragMove только если нажата левая кнопка мыши
this.DragMove();
}
};
}
private void MinimizeWindow(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void MaximizeRestoreWindow(object sender, RoutedEventArgs e)
{
if (this.WindowState == WindowState.Maximized)
this.WindowState = WindowState.Normal;
else
this.WindowState = WindowState.Maximized;
}
private void CloseWindow(object sender, RoutedEventArgs e)
{
this.Close();
}
}
Спасибо @Sinatr !! Установка свойства Background
для элемента Border
сработала. Для следующих поисков в Google у меня теперь это, и оно работает
<Border Height="40" VerticalAlignment="Top"
Background="{StaticResource ColorPrimary500}"
x:Name="TitleBar"
Panel.ZIndex="1">
Ответ или решение
Когда вы разрабатываете пользовательский интерфейс в WPF и создаете собственную панель заголовка окна, важно помнить о способах взаимодействия пользователя с окнами. В случае, представленном вами, функция DragMove()
срабатывает только на элементе TextBlock
, а не на Border
. Это связано с тем, что Border
изначально не имеет заднего фона и, следовательно, не может обрабатывать события мыши, включая нажатия.
Проблема
Ваша основная проблема заключается в том, что Border
без установленного фона игнорирует события мыши. В WPF все рабочие элементы, такие как кнопки, текстовые блоки и панель управления, должны иметь фокусируемую область. Когда Border
не имеет фона (т.е. прозрачный), клики по нему не регистрируются, что и препятствует вызову функции DragMove()
.
Решение
Как вы уже выяснили, простое решение состоит в том, чтобы установить цвет фона для вашего Border
. Как только вы сделали Background="{StaticResource ColorPrimary500}"
, события мыши начали обрабатываться корректно. Это стало возможным благодаря тому, что теперь Border
стал "непрозрачным" на уровне визуализации, что позволяет ему реагировать на ввод.
Вот упрощенный пример кода, чтобы вы могли убедиться, что исправления были приняты:
<Border Height="40" VerticalAlignment="Top"
Background="{StaticResource ColorPrimary500}"
x:Name="TitleBar"
Panel.ZIndex="1">
<DockPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal" DockPanel.Dock="Left">
<TextBlock Text="WPF Application" FontSize="16" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Right" HorizontalAlignment="Right">
<Button Width="40" Content="_" Click="MinimizeWindow" Background="Transparent"/>
<Button Width="40" Content="▢" Click="MaximizeRestoreWindow" Background="Transparent"/>
<Button Width="40" Content="X" Click="CloseWindow" Background="Transparent"/>
</StackPanel>
</DockPanel>
</Border>
Как это работает
Когда фон Border
становится видимым, теперь он принимает клики мыши. Ваша обработка событий в C# также остается неизменной:
TitleBar.MouseDown += (sender, e) =>
{
if (e.ButtonState == System.Windows.Input.MouseButtonState.Pressed)
{
this.DragMove();
}
};
Важные моменты для запоминания
- Фон элемента: Всегда устанавливайте фон для элементов, которые должны обрабатывать события мыши, особенно для контейнеров, таких как
Border
илиGrid
. - Обработка событий: Убедитесь, что обработчики событий привязаны к родительским контейнерам, если вы хотите, чтобы события мыши срабатывали на всей области.
- Проверка состояния кнопок мыши: Не забывайте проверять состояние кнопок мыши (как вы это и сделали) при обработке событий, чтобы избежать ненужных вызовов методов.
Таким образом, вы получили рабочее и полностью функциональное пользовательское окно, используя преимущества WPF. Ваш новый интерфейс теперь отзывчивый и приятный для пользователя, что всегда является ключом к успешной разработке программного обеспечения.