I have two radio buttons and if i put the attribute IsChecked in XAML, the program crashes with a System.NullReferenceException. Additional information: Object reference not set to an instance of an object.
My radio buttons:
<RadioButton IsChecked="True" Name="Mint" Checked="Mint_Checked_1"
Foreground="Red" FlowDirection="RightToLeft" VerticalAlignment="Top"
HorizontalAlignment="Right" Margin="10,30,10,0" GroupName="Update_When"
Content="A">
</RadioButton>
<RadioButton IsChecked="False" Name="Changet" Checked="Changet_Checked_1"
FlowDirection="RightToLeft" VerticalAlignment="Top" HorizontalAlignment="Right"
Margin="10,53,10,0" GroupName="Update_When" Content="B">
</RadioButton>
My event code:
private void Mint_Checked_1(object sender, RoutedEventArgs e)
{
Mint.Foreground = Brushes.Red;
Changet.Foreground = Brushes.Black;
}
private void Changet_Checked_1(object sender, RoutedEventArgs e)
{
Mint.Foreground = Brushes.Black;
Changet.Foreground = Brushes.Red;
}
You are getting that exception because you are calling the checked event before the element is initialized, one way to solve this is to move the IsChecked=True to a Loaded event:
private void MyWindow_Loaded (object sender, RoutedEventArgs e)
{
Mint.IsChecked = true;
}
This worked for me, I moved the xaml line for the RadioButton that was to be checked to the last line in the sequence as follows:
Original order in XAML file, (This order causes an exception to be thrown)
RadioButton x:Name="RadioButton1"
RadioButton x:Name="RadioButton2" // Radio button that is initialized as selected (Is_Checked)
RadioButton x:Name="RadioButton3"
RadioButton x:Name="RadioButton4"
NO exception:
RadioButton x:Name="RadioButton1"
RadioButton x:Name="RadioButton3"
RadioButton x:Name="RadioButton4"
RadioButton x:Name="RadioButton2" // Radio button that is initialized as selected (checked)
I believe this is because when a radio button changes to "Is_checked" (even on initialization) it calls the RadioButton_IsChecked method to which it is bound.
So, during initialization RadioButton1 was initialized to false, then RadioButton2 was initialized to true which called the bound method and RadioButton3 and RadioButton4 were still not initialized and were null which caused the exception.
Note, the above does not change the location of the Radio Buttons on the form.
Also, I have bound all 4 radio buttons to the same method and use if/else if/else if/else to set the form properties I want when a button is checked.
Related
I have a list of devices and in that list user will select which COM port represents which device, each device has its own StackPanel shown below:
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Width="140" Text="IMT" VerticalAlignment="Center"/>
<ComboBox Width="250" Margin="0,0,40,0" x:Name="FM_list" SelectionChanged="DeviceSelected"/>
<TextBlock x:Name="FM_selection" Margin="0,0,40,0" Width="80 "/>
<Button Background="Red" Width="50" Click="Port_selected" x:Name="FM_selection1"/>
</StackPanel>
After user makes his selection in the ComboBox it is verified by clicking an adjecent Button.
I'd like it so that when the Button is clicked x:Name of the TextBlock (or an alternate way of referencing) is passed to the Port_selected function so I can get the correct device when calling TextBox.Name on the sender.
I could a seperate x:Name for each of those buttons and a dictionary to match which button matches which TextBlock and which StackPanel, but I'd like to know how to do without that workaround. Right now I just strip the last char of the Button's x:Name...
Port_selected is an event handler and you cannot pass a string value to this one.
If you are familiar with the MVVM design pattern there are better ways to solve this, for example using commands and command parameters, but the easiest solution given your current setup is probably to get a reference to the TextBlock in the event handler and then get the value of its Name property, e.g.:
private void Port_selected(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
StackPanel stackPanel = btn.Parent as StackPanel;
if (stackPanel != null)
{
TextBlock textBlock = stackPanel.Children
.OfType<TextBlock>()
.FirstOrDefault(x => !string.IsNullOrEmpty(x.Name));
if (textBlock != null)
{
string name = textBlock.Name;
//...
}
}
}
I have a list of CheckBox'es. I would like the user to select at least one before click the next button.
I would want the Button to remain Enabled, but use a TextBlock below the CheckBox to show the prompt to select at least one CheckBox.
How can I check that.
Code:
XAML
<CheckBox x:Name="CheckBox1" Content="CheckBox1" />
<CheckBox x:Name="CheckBox2" Content="CheckBox2" />
<CheckBox x:Name="CheckBox3" Content="CheckBox3" />
<CheckBox x:Name="CheckBox4" Content="CheckBox4" />
<Button x:Name="NextButton" Click="NextButton_Click"/>
Code Behind
private void NextButton_Click(object sender, RoutedEventArgs e) {
if (CheckBox1.IsChecked ?? false) {
// do something
}
// same for other checkBoxes
}
private void NextButton_Click(object sender, RoutedEventArgs e)
{
if (!CheckBox1.IsChecked && !CheckBox2.IsChecked && !CheckBox3.IsChecked && !CheckBox4.IsChecked)
{
// update TextBlock to alert the user
}
else
{
if (CheckBox1.IsChecked)
{
// do something
}
// same for other checkboxes
}
}
You can also do the following, based on the example of just one CheckBox:
XAML
<CheckBox x:Name="CheckBox1" Content="CheckBox1" Checked="CheckBox1_OnChecked"/>
// after all your CheckBoxes insert TextBlock below
// which is Visible by default (but invisible once any CheckBox is checked)
<TextBlock x:Name="TextBlock" Visibility="Visible" Text="Please, select at least 1 checkbox"/>
<Button x:Name="NextButton" Click="NextButton_Click" Height="Auto" Width="Auto" Content="Button"/>
Code Behind
private void NextButton_Click(object sender, RoutedEventArgs e)
{
// your code
}
// We make Visibility of TextBox hidden
// Think for yourself how to take into account
// several CheckBoxes checked vs unchecked
private void CheckBox1_OnChecked(object sender, RoutedEventArgs e)
{
TextBlock.Visibility = Visibility.Hidden;
}
Think for yourself how to take into account several CheckBoxes checked vs unchecked, you may also use CheckBoxes event handler for Unchecked event: Unchecked="CheckBox1_OnUnchecked"
I have such xaml code:
<Grid x:Name="boardGrid">
<Grid.ContextMenu>
<ContextMenu Opacity="0.7" x:Name="menuContext">
</ContextMenu>
</Grid.ContextMenu>
</Grid>
I generate grid's items in code behind. What I want is to disable context menu opening on right click. I want to open it when certains conditions occur.
This is what I have in .cs file:
generating Unit's objects and putting them into Grid;
each object has unit.MouseRightButtonUp += unit_MouseRightButton
void unit_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (CurrentGame.CurrentPlayer.HasTurn == false) return;
.....
ContextMenu.IsOpen = true;
}
So it means that Contextmenu should be open only if condition is fulfilled but it opens anyway.
You can set the attached property ContextMenuService.IsEnabled to false. Then you can manually popup the ContextMenu.
You must set that property for the GUI element that owns the menu. Setting it for the menu itself will do nothing.
<Grid x:Name="boardGrid" ContextMenuService.IsEnabled="false">
<!-- ... -->
</Grid>
void unit_MouseRightButtonUp(object sender, MouseButtonEventArgs e) {
if (CurrentGame.CurrentPlayer.HasTurn == false) return;
.....
boardGrid.ContextMenu.IsOpen = true;
}
I have a DataGrid. One of the columns is a template with a CheckBox in it. When the Checked or Unchecked events trigger, (it happens with both) the CheckBox's DataContext is sometimes null, which causes my code to error. It seems to be null most often if the mouse is moving while you press and release the button quickly (it's intermittent).
I listened for changes to the DataContext of the CheckBox by making views:ListenCheckBox (extends CheckBox) and attaching a binding, and it's never set to null, but it is set from null to a Task at times I wouldn't expect, i.e. after the DataGrid has been totally generated and you're checking/unchecking boxes. Immediately after the [un]checked event runs with a null DataContext, I get the notification that shows the DataContext changed from null to a Task, so it appears that when I get a null DataContext, it's because it hadn't actually set the DataContext by the time it ran the Checked/Unchecked event.
Also, I added Tag="{Binding}" to the CheckBox for debugging. The Tag is not null (i.e. it has the proper object) more often than the DataContext, but still not all the time.
Here are the relevant bits of the XAML code:
<navigation:Page.Resources>
<sdk:DataGridTemplateColumn x:Key="DeleteOrPrintSelect" Header="Delete Or Print Notes Selection">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<views:ListenCheckBox IsChecked="{Binding DeleteOrPrintNotesSelection, Mode=TwoWay}" Checked="DeletePrintNotesCheckBox_Changed" Unchecked="DeletePrintNotesCheckBox_Changed" HorizontalAlignment="Center" VerticalAlignment="Center" Tag="{Binding}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</navigation:Page.Resources>
<sdk:DataGrid x:Name="dataGrid1" Grid.Column="1" Grid.Row="2" AutoGeneratingColumn="dataGrid1_AutoGeneratingColumn">
<sdk:DataGrid.RowGroupHeaderStyles>
[removed]
</sdk:DataGrid.RowGroupHeaderStyles>
</sdk:DataGrid>
And the relevant code behind:
// Create a collection to store task data.
ObservableCollection<Task> taskList = new ObservableCollection<Task>();
[code adding Tasks to taskList removed]
PagedCollectionView panelListView = new PagedCollectionView(taskList);
this.dataGrid1.ItemsSource = panelListView;
}
private void dataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName == "DeleteOrPrintNotesSelection")
{
e.Column = Resources["DeleteOrPrintSelect"] as DataGridTemplateColumn;
}
else
{
e.Column.IsReadOnly = true;
}
}
private void DeletePrintNotesCheckBox_Changed(object sender, RoutedEventArgs e)
{
try
{
var cb = sender as CheckBox;
var t = cb.DataContext as Task;
t.DeleteOrPrintNotesSelection = cb.IsChecked == true;
PagedCollectionView pcv = this.dataGrid1.ItemsSource as PagedCollectionView;
ObservableCollection<Task> taskList = pcv.SourceCollection as ObservableCollection<Task>;
bool anySelected = taskList.Any(x => x.DeleteOrPrintNotesSelection);
this.btnPrint.IsEnabled = anySelected;
this.btnDelete.IsEnabled = anySelected;
}
catch (Exception ex)
{
ErrorMessageBox.Show("recheck", ex, this);
}
}
Any ideas? Thanks in advance.
I found that the problem happened when you double click on the cell and it moved it to the cell editing template. In my case, I didn't have a cell editing template defined, so it used the same cell template, but instead of not changing anything, it apparently decided to make a new check box. I set the column's IsReadOnly property to true, and it fixed it. An alternate solution:
DataContext="{Binding}" (in XAML, or the code equivalent:)
cb.SetBinding(FrameworkElement.DataContextProperty, new Binding());
I'm not sure why this one fixes it, since I thought the default DataContext is {Binding}. Perhaps it's a Silverlight bug, and it gets set in a different order if you define it explicitly instead of leaving it the default.
What is the WPF equivalent for WinForms radio button CheckedChanged?
I have your basic 2 radio button set up, where when one is selected a textbox is enabled and when the other is selected it is disabled.
For the time being I was using RadioButton_Checked, except, I set IsChecked true for one button in the xaml. When I reference the textbox in that Checked method it throws NullReferenceException...
edit:
XAML:
<RadioButton Name="rb1" IsChecked="True" GroupName="1" Checked="rb1_Checked"></RadioButton>
<RadioButton Name="rb2" GroupName="1" Checked="rb2_Checked"></RadioButton>
C#:
private void rb2_Checked(object sender, RoutedEventArgs e)
{
txt.IsEnabled = false;
}
private void rb1_Checked(object sender, RoutedEventArgs e)
{
txt.IsEnabled = true; //null reference here on load
}
Can't you bind the enabled property of the textbox to the checked property of the appropriate radio button in your xaml?
<Textbox IsEnabled="{Binding ElementName=rb2, Path=IsChecked}" />