Diskuze: WPF - mouse event
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
stále nikdo netuší, nebo to tu zapadlo a umřelo?
martinsakra:11.12.2013 11:40
testování a úpravami jsem došel na zajímavé zjištění, pokud držím ctrl a dělám akci tak se to něděje jinak ano. Viz kód:
private void Rect_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
Msquare square;
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
int selected = SamplesListBox.SelectedIndex;
square = msW.SquareType [selected];
msW [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2] = square;
RectangleFill(rectangles [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2], square.Picture);
}
else
{
square = msW [((Tuple<int, int>)((Rectangle)sender).Tag).Item1, ((Tuple<int, int>)((Rectangle)sender).Tag).Item2];
square.Rotate(1);
RectangleFill(((Rectangle)sender), square.Picture);
}
}
private void RectangleFill(Rectangle r, System.Drawing.Bitmap b)
{
r.Fill = new ImageBrush(System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(b.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()));
}
Je to divný, a nenapadá mě žádný rozumný důvod proč by to mělo
fungovat divně. A ano přehodil jsem mousebuttonUp na Down ale žádnej
rozdíl. A nemám jinde ve Formu jinej event MouseButtonUp/Down kterej by to
odchytil.
Ještě mám pro každej Rectangle danej Focus(), když na něho najedu
myší,ale jeho odstraněním se nic nezměnilo.
coells:11.12.2013 12:02
V prvním příspěvku jsi jaksi zapomněl zmínit, že tam máš ListBox. Tvůj handler je nepodstatný, důležitý je zbytek aplikace.
Pokud je Rectangle v jiném controlu, dojde k odchycení PreviewMouseButtonUp/Down události a bude to fungovat přesně tak, jak ti to funguje. To je docela rozumný důvod.
martinsakra:11.12.2013 16:37
Takže pokud to chápu správně, při kliku se mi teď děje, že se jako
první zavolá event PreviewMouseLeftButtonDown, ten díky tomu že je preview
postupuje "z vrchu" od gridu níž. Tj občas se stane že ho odchytne listbox
aniž by měl?
Ale jak to vyřešit teda? Zkusil jsem už i hodit list box do canvasu,ale to
není řešení.
coells:11.12.2013 19:53
Řekl bych, že by sis rozhodně měl koupit knížku o WPF a něco málo se o něm naučit, než začneš dělat složitější aplikace. Někde ti něco zastavuje zpracování událostí, jenže nemáš tušení, jak RoutedEvents fungují, ani jak zjistit, kde se to děje. Já to na dálku zjistit neumím.
Existuje metoda, která to umí obejít, jenže takový postup narušuje standardní zpracování událostí:
rectangle.AddHandler(Window.MouseLeftButtonUpEvent, new MouseButtonEventHandler(__handler), true);
Tenhle kód mi funguje bez problémů (třikrát Rectangle v ListBoxu):
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Background="Yellow">
<ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="Blue" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
</ListBoxItem>
<ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="Green" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
</ListBoxItem>
<ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="Red" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
</ListBoxItem>
</ListBox>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Rectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
(sender as Rectangle).Fill = Brushes.BlanchedAlmond;
}
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
(sender as Rectangle).Fill = Brushes.Gray;
}
}
martinsakra:11.12.2013 20:11
Pozor mám pocit že jsme si trochu nerozuměli. Já nemám listbox ve
kterém jsou rectangly, kdyby to bylo takhle tak bych se prakticky nedivil že
mi blbne mousebutton up/down atd.
já mám Grid obsahující A) canvas-1 do kterého vkládám rectangly,
B)canvas-2 ve kterem je listbox C) 2 dva buttony
To je ten důvod proč mě to přišlo divný, níkdy po cestě nahoru/dolu
nebylo nic co by tomu mohlo bránit
coells:11.12.2013 20:25
V tom není rozdíl, stále mi to funguje dobře:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Canvas Background="LightBlue" Grid.Row="0">
<Rectangle Fill="Blue" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Height="61" Width="107" Canvas.Left="352" Canvas.Top="60" />
<Rectangle Fill="Green" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Height="89" Width="121" Canvas.Left="202" Canvas.Top="32" />
<Rectangle Fill="Red" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Height="91" Width="97" Canvas.Left="60" Canvas.Top="32" />
</Canvas>
<ListBox Background="Yellow" Grid.Row="1">
<ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="Blue" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
</ListBoxItem>
<ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="Green" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
</ListBoxItem>
<ListBoxItem Height="50" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="Red" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
</ListBoxItem>
</ListBox>
</Grid>
</Window>
martinsakra:11.12.2013 20:32
Myslím že problém bude nakonec trochu jiný, vypadá to že pokud se s myší pohne při kliku "nějak" tak se událost nesejme, to co jsem myslel že mám za chybu se děje i tu toho tvýho, prostě velmi rychle měním rectangly a klikám na ně (pokaždé na jiné místo/jiný rectangle) na stejný rychlé klikání funguje. (změnšil jsem si kvuli tomu rectangly a dal je blízko sebe abych to vyzkoušel)
Dík za pomoc
coells:11.12.2013 20:39
Pověs si event handler přímo na Grid, na konci bude container obsahovat nadřazený canvas a OriginalSource je visual, který splňuje hit-testing.
private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource is Rectangle)
{
Rectangle r = e.OriginalSource as Rectangle;
FrameworkElement container = r;
while (container != null && !(container is Canvas))
container = container.Parent as FrameworkElement;
e.Handled = true;
}
}
Zobrazeno 11 zpráv z 11.