#c# #wpf #xaml
#c# #wpf #xaml
Вопрос:
Я новичок в WPF, и я столкнулся с проблемой в этом. Я создаю простое видеоприложение, и в приложении есть 3 столбца. 2-й столбец — это разделитель сетки, а 3-й столбец — это элемент MediaElement и StackPanel (содержащий элементы управления видео) поверх него.
Чего я хочу добиться, так это того, чтобы панель стека исчезала, когда указатель мыши входит в элемент MediaElement, и исчезала из панели стека, когда указатель мыши выходит из элемента MediaElement. Однако проблема возникает, когда указатель мыши попадает на панель стека, что вызывает эффект исчезновения (произойдет событие MouseExit элемента MediaElement).
<Window x:Class="WPF_learningapp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:MyNamespace="clr-namespace:WPF_learningapp"
Title="MiDrama" Height="350" Width="700" ResizeMode="CanResize">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Custom assets/CustomScrollbar.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<MyNamespace:PausePlayBooleanConverter x:Key="PausePlayBooleanConverter" />
</ResourceDictionary>
</Window.Resources>
<MyNamespace:GridControl>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="0" MaxWidth="300"/>
<ColumnDefinition Width="1"/>
<ColumnDefinition Width= "*">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel/>
<GridSplitter Grid.Column="1" Width="1" HorizontalAlignment="Stretch" />
<MediaElement Grid.Column="2" Name="myMediaPlayer" LoadedBehavior="Manual" Stretch="Fill">
<MediaElement.Triggers>
<EventTrigger RoutedEvent="MouseEnter" >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VideoControlPanel"
From="0.0" To="1.0" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VideoControlPanel"
From="1.0" To="0" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</MediaElement.Triggers>
</MediaElement>
<StackPanel Name="VideoControlPanel" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="59" Margin="55,0,41,4" Background="Transparent">
<Slider Name="VideoSlider" Thumb.DragStarted="slider_DragStarted" Thumb.DragCompleted="slider_DragCompleted" Margin="0,0,0,5"
IsMoveToPointEnabled="True" ValueChanged="slider_ValueChanged"/>
<WrapPanel HorizontalAlignment="Center">
<Button Content="{Binding Path=isPlaying, Converter={StaticResource PausePlayBooleanConverter}}" Height="34" Width="50" Margin="5 0" Name="playpause_Btn" Click="playpause_Btn_Click"/>
<Button Height="34" Width="50" Content="Stop" Margin="5 0" Name="stop_Btn" Click="stop_Btn_Click"/>
</WrapPanel>
</StackPanel>
</MyNamespace:GridControl>
Я попытался инкапсулировать все в canvas в сетке, но панель управления не изменит размер должным образом. Похоже, что даже реализация триггера события в столбце сетки не работает. Есть ли способ добиться этого? Пожалуйста, дайте совет.
Ответ №1:
Я бы сказал, что вам следует поместить EventTrigger для MouseLeave на StackPanel или, возможно, на содержимое StackPanel — не на MediaElement.
Редактировать
Хорошо, я думал, что stackpanel покрывает весь medialelement (я не видел реквизит высоты).
Решением могло бы быть размещение mediaelement и stackpanel внутри какого-либо элемента управления контентом, как в примере ниже:
<Window x:Class="SO40188046.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:SO40188046"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Border Background="Blue">
<Border.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VideoControlPanel" From="0.0" To="1.0" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VideoControlPanel" From="1.0" To="0" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<Grid>
<MediaElement Source="SOME MEDIA URI" />
<Border Name="VideoControlPanel" Background="Red" Height="100" VerticalAlignment="Bottom" Opacity="0" />
</Grid>
</Border>
</Window>
ПРАВКА 2:
Здесь я изменил ваш собственный ответ, поэтому для определения размера и положения элементов управления не требуется никакого кода. Я заменил Canvas ContentControl и заменил некоторые другие элементы управления. Но общий макет тот же:
<Window x:Class="WPF_learningapp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:MyNamespace="clr-namespace:WPF_learningapp"
Title="MiDrama" Height="350" Width="700" ResizeMode="CanResize">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Custom assets/CustomScrollbar.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<MyNamespace:PausePlayBooleanConverter x:Key="PausePlayBooleanConverter" />
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="0" MaxWidth="300"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width= "*">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel/>
<GridSplitter Grid.Column="1" Width="4" HorizontalAlignment="Center" VerticalAlignment="Stretch" />
<ContentControl Grid.Column="2" Background="AliceBlue">
<ContentControl.Triggers>
<EventTrigger RoutedEvent="MouseEnter" >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="VideoControlPanel"
From="0.0"
To="1.0"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="VideoControlPanel"
From="1.0"
To="0"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ContentControl.Triggers>
<Grid>
<MediaElement
Name="myMediaPlayer"
Stretch="Fill" />
<Grid Name="VideoControlPanel" VerticalAlignment="Bottom" Height="60" Background="Transparent" Opacity="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Slider
Name="VideoSlider"
Grid.Column="0"
Grid.ColumnSpan="2"
Thumb.DragStarted="slider_DragStarted"
Thumb.DragCompleted="slider_DragCompleted"
Margin="10,5"
IsMoveToPointEnabled="True"
ValueChanged="slider_ValueChanged"/>
<Button
Grid.Column="0"
Grid.Row="1"
HorizontalAlignment="Right"
Content="Play"
Height="26"
Width="50"
Name="playpause_Btn"
Click="playpause_Btn_Click"/>
<Button
Grid.Column="1"
Grid.Row="1"
HorizontalAlignment="Left"
Height="26"
Width="50"
Content="Stop"
Name="stop_Btn"
Click="stop_Btn_Click"/>
</Grid>
</Grid>
</ContentControl>
</Grid>
</Window>
Комментарии:
1. Я не могу этого сделать, StackPanel — это всего лишь небольшая часть внутри сетки, и я хочу, чтобы она появлялась, как только я вхожу в сетку. Единственный элемент управления, который покрывает всю сетку, — это MediaElement.
2. ?? Кто вы и почему отклоняете?
3. Я обновил свой код xaml. Я не думаю, что рисование границы сработает, мне нужна анимация, 1. Введите мышью 3-й столбец, отобразите StackPanel. 2. Мышь выходит из 3-го столбца, удалите StackPanel.
4. @Ytan: Но граница — это всего лишь пример элемента управления содержимым. Вы можете, например, скопировать весь мой код из <Border … /Border> и поместите это в свой третий столбец и измените Border на ContentControl или что-либо еще, что вы хотите, и это будет работать так, как вы описываете… Вы должны самостоятельно подумать о пути нашего ответа, иначе это не стоит того, чтобы беспокоиться 🙂
5. Я вижу, наконец, я просто инкапсулировал все в третий столбец внутри canvas и вручную изменил размер всего внутри. Я думал, что будет более простая альтернатива. Я также обновил свой пользовательский интерфейс xaml.
Ответ №2:
Это решение проблемы, описанной выше. Поместите все внутри canvas в ячейку сетки (которая, я думаю, является единственным контейнером, с которым легко работать с перекрывающимися элементами управления).
<Window x:Class="WPF_learningapp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:MyNamespace="clr-namespace:WPF_learningapp"
Title="MiDrama" Height="350" Width="700" ResizeMode="CanResize">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Custom assets/CustomScrollbar.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<MyNamespace:PausePlayBooleanConverter x:Key="PausePlayBooleanConverter" />
</ResourceDictionary>
</Window.Resources>
<MyNamespace:GridControl>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="0" MaxWidth="300"/>
<ColumnDefinition Width="1"/>
<ColumnDefinition Width= "*">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel/>
<GridSplitter Grid.Column="1" Width="1" HorizontalAlignment="Stretch" />
<Canvas Grid.Column="2" Name="VideoCanvas" SizeChanged="VideoCanvas_sizeChanged" Background="AliceBlue">
<Canvas.Triggers>
<EventTrigger RoutedEvent="MouseEnter" >
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VideoControlPanel"
From="0.0" To="1.0" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VideoControlPanel"
From="1.0" To="0" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
<MediaElement Grid.Column="2" Name="myMediaPlayer" LoadedBehavior="Manual" Stretch="Fill" Height="{Binding Path=ActualHeight, ElementName=VideoCanvas}" Width="{Binding Path=ActualWidth, ElementName=VideoCanvas}"/>
<StackPanel Name="VideoControlPanel" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="59" Background="Transparent" Canvas.Left="10" Canvas.Top="250" Width="371">
<Slider Name="VideoSlider" Thumb.DragStarted="slider_DragStarted" Thumb.DragCompleted="slider_DragCompleted" Margin="0,0,0,5"
IsMoveToPointEnabled="True" ValueChanged="slider_ValueChanged"/>
<WrapPanel HorizontalAlignment="Center">
<Button Content="{Binding Path=isPlaying, Converter={StaticResource PausePlayBooleanConverter}}" Height="34" Width="50" Margin="5 0" Name="playpause_Btn" Click="playpause_Btn_Click"/>
<Button Height="34" Width="50" Content="Stop" Margin="5 0" Name="stop_Btn" Click="stop_Btn_Click"/>
</WrapPanel>
</StackPanel>
</Canvas>
</MyNamespace:GridControl>
</Window>
Комментарии:
1. Смотрите мою ПРАВКУ 2 в моем ответе.