Can't access the events inside the GridViewColumn's Content - c#

When I add an event to the ListViewItem,
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewMouseDown" Handler="listViewItem_MouseDown" />
</Style>
Then add another event in the content inside the GridViewColumn,
<GridViewColumn Header="Action">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image x:Name="imgEdit"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Width="40"
Height="40"
Tag="{Binding ProductBarcode}"
Cursor="Hand"
MouseDown="img_MouseDown">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/Resources/edit_button.png" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="/Resources/edit_button_hovered.png" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I can't fire the event in the Image control. The one that is firing is the event in the ListViewItem. How to access the event in the Image control?
Here are the events:
private void img_MouseDown(object sender, MouseButtonEventArgs e)
{
switch ((sender as Image).Name)
{
case "imgEdit":
MessageBox.Show("EDIT");
break;
default:
break;
}
}
private void listViewItem_MouseDown(object sender, RoutedEventArgs e)
{
MessageBox.Show("ROW CLICKED");
}

The PreviewMouseDown event of the ListViewItem will always be raised before the MouseDown event of the Image. This is how routed events work: https://msdn.microsoft.com/en-us/library/ms742806(v=vs.110).aspx. PreviewMouseDown is a tunneling event and MouseDown is a bubbling event.
If you don't want to handle the PreviewMouseDown event when the Image is clicked you could check the type of the OriginalSource of the RoutedEventArgs and return immediately from the event handler if it is Image:
private void listViewItem_MouseDown(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is Image)
return; // do nothing
MessageBox.Show("ROW CLICKED");
}

Try:
private void listViewItem_MouseDown(object sender, MouseButtonEventArgs e)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
MessageBox.Show("ROW CLICKED");
}));
}

Related

How do I make a textbox visible and hidden with a checkbox?

So I am trying to make my textbox invisible when a checkbox is not checked. Everything works fine untill I check the box and then uncheck it again. The textbox will stay visible.
private void chbon_Checked_1(object sender, RoutedEventArgs e)
{
if (cchbon.IsChecked == true)
{
txtshow.Visibility = System.Windows.Visibility.Visible;
}
if (chbon.IsChecked == false)
{
txtshow.Visibility = System.Windows.Visibility.Hidden;
}
}
This is the XAML for the Checkbox:
<CheckBox x:Name="chbon" Content="On" HorizontalAlignment="Left" Margin="175,84,0,0" VerticalAlignment="Top" Checked="chbon_Checked_1"/>
<TextBox x:Name="txtshow" HorizontalAlignment="Left" Height="23" Margin="272,82,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="29" Visibility="Hidden"/>
The event Checked does not fire when uncheck happens.
The event Unchecked is for that purpose.
... Checked="chbon_Checked" Unchecked="chbon_Unchecked"/>
and no need to monitor cchbon.IsChecked in code behind:
private void chbon_Checked(object sender, RoutedEventArgs e)
{
txtshow.Visibility = System.Windows.Visibility.Visible;
}
private void chbon_Unchecked(object sender, RoutedEventArgs e)
{
txtshow.Visibility = System.Windows.Visibility.Hidden;
}
Alternatively, you can do it via binding and a converter:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
...
<CheckBox x:Name="chbon"/>
<TextBox x:Name="txtshow" Visibility="{Binding ElementName=chbon, Path=IsChecked,
Converter={StaticResource BoolToVis}, FallbackValue=Hidden}"/>
Note that,
Once you managed this approach you may want to implement a custom converter since the built-in BooleanToVisibilityConverter returns Visible/Collapsed for True/False input (and not Visible/Hidden)
The Checked event handler will only hit when you check the checkbox, not uncheck it. You can also use the Unchecked handler in your XAML that would make the textbox hidden.
private void chbon_Unchecked(object sender, RoutedEventArgs e)
{
txtshow.Visibility = System.Windows.Visibility.Hidden;
}
private void chbon_Checked_1(object sender, RoutedEventArgs e)
{
txtshow.Visibility = System.Windows.Visibility.Visible;
}
when CheckBox goes to unchecked state, Unchecked event fires (simmetric to Checked). Add event handler to both of them.
<CheckBox x:Name="chbon"
Content="On"
HorizontalAlignment="Left"
Margin="175,84,0,0"
VerticalAlignment="Top"
Checked="chbon_Checked_1"
Unhecked="chbon_Checked_1"/>
private void chbon_Checked_1(object sender, RoutedEventArgs e)
{
txtshow.Visibility = cchbon.IsChecked ? Visibility.Visible : Visibility.Hidden;
}
It is common to use binding to boolean property to set Visibility of some element. There is a BooleanToVisibilityConverter in .NET, which returns Visible for true, and Collapsed for false. Collapsed is different from Hidden: Hidden element stil claims the space on the screen as if it was Visible.
There is a way to achieve everything in XAML using a Trigger:
<CheckBox x:Name="chbon" Content="On"
HorizontalAlignment="Left" Margin="175,84,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtshow"
HorizontalAlignment="Left" VerticalAlignment="Top"
Height="23" Width="29" Margin="272,82,0,0" TextWrapping="Wrap">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=chbon}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
<TextBox/>

Changing text in textblock to italicized on MouseEnter

I have a textblock that contains some non-italicized text. When the mouse enters the textblock, the text changes through the use of the code behind. I would like the code behind to also have the ability to change the text to italicized. This is what I have so far:
XAML:
<TextBlock x:Name="block1"
Background="Cyan"
Foreground="{StaticResource myBrush2}"
Grid.Column="0"
Grid.Row="0"
Height="30"
HorizontalAlignment="Center"
MouseEnter="TextBlock_MouseEnter"
MouseLeave="TextBlock_MouseLeave"
Padding="0,7,0,0"
Text ="Hover Me!"
TextAlignment="Center"
Width="100"/>
Code Behind (C#):
public void TextBlock_MouseEnter(object sender, MouseEventArgs e)
{
string blockName = ((TextBlock)sender).Name;
var block = sender as TextBlock;
if (block != null && blockName == "block1")
{
block.Text = "Yo! I'm TextBlock1";
}
}
I have looked into using System.Drawing and the use of FontStyle.Italic; although I was unsuccessful of actually making it work.
This is what XAML was made for
<TextBlock x:Name="block1"
Background="Cyan"
Foreground="{StaticResource myBrush2}"
Grid.Column="0"
Grid.Row="0"
Height="30"
HorizontalAlignment="Center"
MouseEnter="TextBlock_MouseEnter"
MouseLeave="TextBlock_MouseLeave"
Padding="0,7,0,0"
Text ="Hover Me!"
TextAlignment="Center"
Width="100">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FontStyle" Value="Italic" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
But, if you really want to, here's an example of how you might implement that functionality from code-behind.
private void block1_MouseEnter(object sender, MouseEventArgs e)
{
SetFontStyle(FontStyles.Italic);
}
private void block1_MouseLeave(object sender, MouseEventArgs e)
{
SetFontStyle(FontStyles.Normal);
}
private void SetFontStyle(FontStyle style)
{
block1.FontStyle = style;
}

Open Buttons ContextMenu on Left Click

I have a button with a context menu, my requirements are to show the context menu on left click
The problem is that the <ContextMenu ItemsSource="{Binding LineItems}" isn't being updated/refresh when the context menu opens. However If i right click first, items are loaded fine
XAML
<Button x:Name="BtnMessageChannel" Click="BtnMessageChannel_Click" Grid.Row="0" Grid.Column="2" Height="23" Width="23" ToolTip="Message Channel" >
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding LineItems}" x:Name="CtxMessageChannel">
<ContextMenu.Resources>
<Image x:Key="img" Source="{Binding Icon}" x:Shared="false"/>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding DisplayName}"/>
<Setter Property="Icon" Value="{StaticResource img}">
</Setter>
</Style>
</ContextMenu.Resources>
</ContextMenu>
</Button.ContextMenu>
<Image Source="Images/mail_send.png" HorizontalAlignment="Left" Width="16" />
</Button>
Code Behind
private void BtnMessageChannel_Click(object sender, RoutedEventArgs e)
{
BtnMessageChannel.ContextMenu.GetBindingExpression(ContextMenu.ItemsSourceProperty)
.UpdateTarget();
BtnMessageChannel.ContextMenu.Visibility = Visibility.Visible;
BtnMessageChannel.ContextMenu.IsOpen = true;
}
Is there any easy solutions to this problem?
An easy solution is to update your button event handler to simulate a right click if the context menu is not currently open.
private void BtnMessageChannel_Click(object sender, RoutedEventArgs e)
{
if (!BtnMessageChannel.ContextMenu.IsOpen)
{
e.Handled = true;
var mouseRightClickEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Right)
{
RoutedEvent = Mouse.MouseUpEvent,
Source = sender,
};
InputManager.Current.ProcessInput(mouseRightClickEvent);
}
}

Unable to Close Form when using DragMove, MouseDown and Custom Button on same Grid

I have an image which has a MouseDown event so that I can close the window: The image also has a Hover via Style.Trigger: The code is minimized for simplicity.
private void btnClose_MouseUp(object sender, MouseButtonEventArgs e)
{
Close();
}
Because the Window is Borderless (WindowStyle = none), I added a MouseDown event so that I can drag it.
private void appWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
this.DragMove();
}
}
The problem is: If I am using the MouseDown with DragMove(), I cannot get the image used as buttons to work. If I comment out the DragMove, then the buttons works.
XAML:
<Image ToolTip="Close" Cursor="Hand" x:Name="btnClose"
Width="26" Height="26" Margin="505,19,19,306" MouseUp="btnClose_MouseUp">
<Image.Resources>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="img/closeNormal.png"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="img/closeHoverWithNoBackground.png"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Resources>
</Image>
All are in the same Grid.
I am also off the grid with ideas to solve this:
try calling base.MouseLeftButtonDown
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (e.LeftButton == MouseButtonState.Pressed)
{
this.DragMove();
}
}

On double click change the name of checkbox present in listbox as item template WPF

I have bound the listbox with checkbox in it.
Now I have to change the name of checkbox on double clicking on it.
How can I change the name of checkbox
(I have to give option to user to change the name of checkbox means user will double click on name of checkbox then name will be replaced by textbox then user can add the name . On blur or suitable event it will be saved to database)
<ListBox AlternationCount="2" Width="140" Margin="18,63,480,24" Name="lstbxCuisines" ItemsSource="{Binding}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="chkCuisine" Height="20" Margin="0,5,0,0" FontSize="12" Tag="{Binding CuisineId}" Content="{Binding Cuisine}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#ffffff"></Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="#f1f6fe"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
</ListBox>
You could add an MouseDoubleClick-Event to your ComboBox:
<DataTemplate>
<CheckBox Name="chkCuisine" Height="20" Margin="0,5,0,0" FontSize="12" Tag="{Binding CuisineId}" Content="{Binding Cuisine}" MouseDoubleClick="chkCuisine_MouseDoubleClick"/>
</DataTemplate>
In your Eventhandler, you can change the Name like so:
private void chkCuisine_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
((ComboBox)sender).Name = "NewName";
}
1 way
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<EventSetter Event="MouseDoubleClick" Handler="CheckBoxDoubleClick"></EventSetter>
</Style>
protected void CheckBoxDoubleClick(object sender, MouseButtonEventArgs e)
{
CheckBox chk = e.Source as CheckBox;
if (chk != null)
{
chk.Content = "Content Changed";
}
}
other way
<ListBox MouseDoubleClick="ListBox_MouseDoubleClick">
private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var chk = FindParentControl<CheckBox>(e.OriginalSource as DependencyObject);
if (chk != null)
{
((CheckBox)chk).Content = "Content Changed";
}
}
private DependencyObject FindParentControl<T>(DependencyObject control)
{
if (control == null)
return null;
DependencyObject parent = VisualTreeHelper.GetParent(control);
while (parent != null && !(parent is T))
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent;
}

Categories