RadioButton Uncheck events not firing in WPF? - wpf

In my WPF Window i have RadioButton with default IsChecked property is true.
How to write code for Uncheck the RadioButton.
I tried with Sipmle example.
I take one radiobutton.
<Grid>
<RadioButton Height="16" Margin="54,103,104,0" GroupName="t" Name="radioButton1" VerticalAlignment="Top" IsChecked="True" Unchecked="radioButton1_Unchecked">Text</RadioButton>
</Grid>
private void radioButton1_Unchecked(object sender, RoutedEventArgs e)
{
radioButton1.IsChecked = false;
}
But its not working
Can any one help on this?
Ramki

First of all, it is not possible to uncheck a radiobutton that is singled out. It would make no sense. That's why your event doesn't get fired.
Now, having a single RadioButton will not help you achieve anything: they are meant to be in a group of RadioButtons. Use a CheckBox instead.
Then in the UnChecked event, you don't have to uncheck it: the event is fired because it was unchecked in the first place =)
<Grid>
<CheckBox Height="16" Margin="54,103,104,0" GroupName="t" Name="checkBox1"
VerticalAlignment="Top" IsChecked="True" Unchecked="checkBox1_Unchecked">Text</CheckBox>
</Grid>
private void checkBox1_Unchecked(object sender, RoutedEventArgs e)
{
MessageBox.Show("checkBox1 has been unchecked!");
}

you can't Uncheck a radiobutton if you haven"t another to check !

Related

WPF event unsubscribe leak in DataTemplate (XAML) on NET Framework

Imagine a UserControl with a ListBox having a CheckBox in a DataTemplate. The ItemsSource for the ListBox is some global list. The CheckBox has Checked/Unchecked events attached to it.
<ListBox ItemsSource="{Binding Source={x:Static a:MainWindow.Source}}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type a:Data}">
<CheckBox Content="{Binding Path=Name}"
Checked="ToggleButton_OnChecked"
Unchecked="ToggleButton_OnUnchecked"
IsChecked="{Binding Path=IsEnabled}"
Padding="10"
VerticalContentAlignment="Center"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I am logging loaded/unloaded/checked/unchecked events in the main window's log.
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
Log("Checked");
}
private void ToggleButton_OnUnchecked(object sender, RoutedEventArgs e)
{
Log("Unchecked");
}
private void UserControl1_OnLoaded(object sender, RoutedEventArgs e)
{
Log("Loaded");
}
private void UserControl1_OnUnloaded(object sender, RoutedEventArgs e)
{
Log("Unloaded");
}
The main window features a dynamic list of UserControl1 instances (starting with just one). There are add/remove buttons that allow me to add more instances.
<UniformGrid Rows="2">
<DockPanel>
<Button DockPanel.Dock="Top" Click="Add">Add</Button>
<Button DockPanel.Dock="Top" Click="Remove">Remove</Button>
<ListBox x:Name="ListBox">
<local:UserControl1 />
</ListBox>
</DockPanel>
<ListBox ItemsSource="{Binding ElementName=This,Path=Log}" FontFamily="Courier New"/>
</UniformGrid>
The window's codebehind:
private void Add(object sender, RoutedEventArgs e)
{
ListBox.Items.Add(new UserControl1());
}
private void Remove(object sender, RoutedEventArgs e)
{
if (ListBox.Items.Count == 0) return;
ListBox.Items.RemoveAt(0);
}
When I run the app there is just one UserControl1 instance. If I add one more and then immediately remove one of them, then click the one and only checkbox on the screen, I see two "Checked" events logged. If I now uncheck it, there are two "Unchecked" events (even though "Unloaded" event was previously clearly logged. The hex numbers on the left show the output of a GetHashCode() which clearly shows the events were handled by distinct UserControl1 instances.
So even though one of UserControl1 gets unloaded, the events don't seem to get unsubscribed automatically. I have tried upgrading to NET Framework 4.8 to no avail. I see the same behavior. If I add 10 new controls and remove them immediately, I will observe 10 "Checked" or "Unchecked" events.
I have tried searching for a similar problem but could not find it. Is there something I am missing or did I just encounter a bug? Looking for workarounds.
Full source code is available on GitHub. https://github.com/wpfwannabe/datacontext-event-leak
In the MVVM pattern, the view is bind to the view model and doesn't survive it when the garbage collection do it's job.
In the example you provided, the view model is a static object and by definition can't be garbage collected, so the view can't neither be garbage collected.
There is no automatic unbinding since you can reuse an instance of an user control (it can be Loaded and UnLoaded multiple times).
The simplest¹ way to fix this memory leak is to do the unbinding on unload :
Wpf
// First give the ListBox a name
<ListBox x:Name="ListBox" ItemsSource="{Binding Source={x:Static a:MainWindow.Source}}">
Code behind
private void UserControl1_OnUnloaded(object sender, RoutedEventArgs e)
{
Log("Unloaded");
ListBox.ItemsSource = null;
}
1: The proper way is to wrap the static list in a dedicated list view model, make the view model disposable (to unbind the wrapper from the static list on dispose), dispose the view model on remove.

Telerik RadTimeline respond to mouse clicks

Is there any way to know if the user has clicked on an item in RadTimeline? I would like to handle the click and do something with the selected timeline item, but my searching hasn't revealed any way to handle this. I can capture the mouse click on MouseLeftButtonDown event, but I don't see a way to tell which item was hit, if any.
According to Telerik, this feature is not supported, but will be available for Q1 2012 SP1 or Q2 2012 release.
However, after researching it, I found a workaround that seems to work. If you override the TimelineItemTemplate with a DataTemplate that has a MouseLeftButtonDown event on it, then you can use the DataContext of the sender to get the bound data.
XAML:
<telerik:RadTimeline x:Name="MatchTimeline" Height="250" PeriodStart="3/1/2012" PeriodEnd="3/30/2012">
<telerik:RadTimeline.Intervals>
<telerik:DayInterval/>
<telerik:HourInterval/>
</telerik:RadTimeline.Intervals>
<telerik:RadTimeline.TimelineItemTemplate>
<DataTemplate>
<Border Height="14">
<Grid>
<Rectangle Height="10" Fill="Blue" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"/>
</Grid>
</Border>
</DataTemplate>
</telerik:RadTimeline.TimelineItemTemplate>
Code:
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MyTimelineItem item = (MyTimelineItem)(((Telerik.Windows.Controls.DataItemBase)(((System.Windows.FrameworkElement)(sender)).DataContext)).DataItem);
item.IWasHere();
}

databinding in silverlight

I have a xaml with a button like this:
Button.xaml
<Grid x:Name="LayoutRoot" >
<StackPanel >
<Button Content="Button1" Click="Button1_Click" />
</StackPanel >
</Grid>
and Button.xaml.cs:
private void Button1_Click(object sender, RoutedEventArgs e)
{
// Get a instance of ClientOversikt
CustomerView childWindow = m_container.Resolve<CustomerView >();
childWindow.Show();
}
It's working fine. But I want to use Databinding in Button.xaml instead of Click="Button1_Click". How could I do it?
I appreciate all the help
Since you're using Silverlight 4, you can use commands. You bind the Command property of the Button to an instance of ICommand, which will open the child window when executed. Then, when you click on the button, the command will be executed.
This page contains a reasonably good introduction to commanding.

Is there any way to alias commands in WPF?

Is there any way to effectively "alias" commands in WPF ? My situation is this : I've created an application that uses ApplicationCommands.Delete in the context of a graphical editor that has a number of customized canvases. Some of the controls that are on these canvases use TextBoxes, but here's the problem : TextBox doesn't respond to ApplicationCommands.Delete, it responds to EditorCommands.Delete. Is there any way to cleanly get TextBox to respond to ApplicationCommands.Delete without subclassing or manually setting bindings on every TextBox instance ?
To answer your specific question, I know of no way to cause two separate routed commands to be treated as the same command. But because ApplicationCommands.Delete is a routed command, after it is delivered to its target, the TextBox and there is no command binding, it will begin bubbling up. So the simplest solution that meets your requirements is to install a command binding for ApplicationCommands.Delete somewhere inbetween the TextBox all the way up to and possibly including the Window, that implements the behavior you desire.
Here's an example that installs a handler on a parent Grid that sends the "right" command the the focused element which in this case will be a TextBox:
<Grid>
<Grid.CommandBindings>
<CommandBinding Command="ApplicationCommands.Delete" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed"/>
</Grid.CommandBindings>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_Edit">
<MenuItem Header="_Delete" Command="ApplicationCommands.Delete"/>
</MenuItem>
</Menu>
<StackPanel>
<TextBox Text="Some text"/>
</StackPanel>
</DockPanel>
</Grid>
and here's the code-behind:
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
EditingCommands.Delete.Execute(null, Keyboard.FocusedElement);
}

How to focus in WPF with WindowsFormHost

I have this simple setup:
<StackPanel>
<TextBox Text="wpf1" PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" />
<TextBox Text="wpf2" PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" />
<WindowsFormsHost>
<wf:TextBox Text="winforms" />
</WindowsFormsHost>
</StackPanel>
private void TextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}
Three textboxes, two WPF and one WinForm. I can't move focus between the two WPF-Textboxes which I desired but I can move focus to the WinForm-Textbox. The event PreviewLostKeyboardFocus does not even triggered when moving from a WPF-Textbox to a WinForm-Textbox. Any clues to why and how this could be solved?
EDIT
I've noticed that WindowsFormsHost.PreviewGotKeyboardFocus is triggered first when focus is leaving the WindowsFormsHost again. Thats odd. Maybe it's a bug?

Resources