C# WPF - DataBinding RadioButtons not working - c#

I have searched several tutorials and tried each option, but I cannot get my radio buttons to bind. When I try to compile the following code I get the error
The resource "nullableBooleanConverter" could not be resolved
Here is what I currently have in XAML:
<RadioButton GroupName="grp_Option_1" Content="Yes" IsChecked="{Binding Path=OpstionSelected, Mode=TwoWay, Converter={StaticResource nullableBooleanConverter}, ConverterParameter=true}" />
<RadioButton GroupName="grp_Option_2" Content="No" IsChecked="{Binding Path=OptionSelected, Mode=TwoWay, Converter={StaticResource nullableBooleanConverter}, ConverterParameter=false}" />
My CS has
public bool OptionSelected
{
get { return optionSelected; }
set
{
optionSelected = value;
this.OnPropertyChanged("OptionSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
Here is my converter:
[ValueConversion(typeof(bool?), typeof(bool))]
public class SuccessConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool param = bool.Parse(parameter.ToString());
if (value == null)
{
return false;
}
else
{
return !((bool)value ^ param);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
bool param = bool.Parse(parameter.ToString());
return !((bool)value ^ param);
}
}
Any help is greatly appreciated!

Try to add the following lines in your <Window.Resources>
<Window x:Class="WpfApplication2.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"
xmlns:Converters="clr-namespace: here.yournamespace.converts">
<Window.Resources>
<Converters:SuccessConverter x:Key="nullableBooleanConverter" />
</Window.Resources>
<Grid>
</Grid>
</Window>

Related

How to change the format of a date

I am receiving the date in this 2018-10-03 format and I would like to switch to this format 03/10/2018
<Label Text="{Binding cmPaymentDate, StringFormat='{0:dd/MM/yyyy}'}" TextColor="White" Font="14"/>
you might try to use converter. Another thing is that it must be a DateTime otherwise stringFormat will have no effect.
<Window x:Class="StackPoC.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:StackPoC"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<StackPanel.Resources>
<local:DateConverter x:Key="DateConverter" />
</StackPanel.Resources>
<TextBlock Text="{Binding CmPaymentDate, Converter={StaticResource DateConverter}}" Foreground="Black" FontSize="14"/>
</StackPanel>
Code-Behind
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private DateTime _cmPaymentDate;
public DateTime CmPaymentDate
{
get
{
return _cmPaymentDate;
}
set
{
_cmPaymentDate = value;
OnPropertyChanged("CmPaymentDate");
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
CmPaymentDate = new DateTime(2018, 09, 23);
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
and the converter:
public class DateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DateTime dt = (DateTime)value;
return dt.ToString("dd/MM/yyyy");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Odd behavior when trying to change a bound RadioButton in WPF

I've bound two radio buttons in my Child window to an Enum in my ViewModel which is constructed in the Main window. The binding works as expected but I have noticed a very odd behavior which I can't solve. I have provided all the code here so you can reconstruct the problem easily for yourself.
Here are the steps to see this odd behavior:
Click on the button in the MainWindow
The ChildWindow opens and the RadioButton is set to User
Choose Automatic and then Choose User again
Close the ChildWindow and reopen it again! Try to change the RadioButton to Automatic. It won't change!
<Window x:Class="RadioButtonBinding.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">
<Button Content="Display Child Window" Click="DisplayChildWindow"/>
</Window>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
DataContext = viewModel;
}
private void DisplayChildWindow(object sender, RoutedEventArgs e)
{
var win = new ChildWindow {DataContext = (ViewModel) DataContext};
win.ShowDialog();
}
}
<Window x:Class="RadioButtonBinding.ChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:radioButtonBinding="clr-namespace:RadioButtonBinding"
Title="ChildWindow" Height="300" Width="300">
<Window.Resources>
<radioButtonBinding:EnumBooleanConverter x:Key="EnumBooleanConverter"/>
</Window.Resources>
<StackPanel>
<RadioButton Content="Automatic"
GroupName="CalcMode"
IsChecked="{Binding Path=CalcMode,
Converter={StaticResource EnumBooleanConverter},
ConverterParameter={x:Static radioButtonBinding:CalcMode.Automatic}}"/>
<RadioButton Content="Custom"
GroupName="CalcMode"
IsChecked="{Binding Path=CalcMode,
Converter={StaticResource EnumBooleanConverter},
ConverterParameter={x:Static radioButtonBinding:CalcMode.User}}"/>
</StackPanel>
</Window>
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private CalcMode calcMode = CalcMode.User;
public CalcMode CalcMode
{
get { return calcMode; }
set
{
calcMode = value;
RaisePropertyChanged("CalcMode");
}
}
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler == null) return;
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class EnumBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var paramEnum = parameter as Enum;
var valueEnum = value as Enum;
return Equals(paramEnum, valueEnum);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var parameterEnum = parameter as Enum;
if (parameterEnum == null)
return DependencyProperty.UnsetValue;
return parameterEnum;
}
}
public enum CalcMode : byte
{
Automatic,
User,
}
UPDATE:
I suspect it must be the Converter but I don't know why? It just falls into a loop.
EDIT
What about converting the enum to bool as follows?
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null || !(bool)value)
return DependencyProperty.UnsetValue;
var parameterEnum = parameter as Enum;
return parameterEnum;
}

Button Enablity WPF

I have a UserControl in which I have a DataDrid and in that DataGrid I have two ComboBoxes. Now what I want to do is when I select any item from both the ComboBoxes the Button which is outside the DataGrid should get enabled.
My DataGrid is bind to an ItemSource so does the Comboboxes.
I tries to use MuliDatatriggers but they failed as button is outside the DataGrid so those ComboBoxes will not be available to it.
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="Combo1" ItemsSource="{Binding Lst1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Code1" SelectedValue="{Binding CodeID1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<ComboBox Name="Combo2" ItemsSource="{Binding Lst2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Code2" SelectedValue="{Binding CodeID2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Name="Add" IsEnabled="{Binding IsAddEnabled,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
There is a lot of answers to this question already posted.
For example: Enable text box when combobox item is selected
The better way for you is to apply MVVM to your application.
I agree with #MikroDel with the MVVM that the only way to work right in wpf.. I do somthing like this but not with two cmbs and not on datagrid but that not need to be different at all because in each combo you set the selected index to your property on the viewModel and the same for button.
in this exemple i use RelayCommand you can read hare about using it, but that not this q subject.
In addition I use a convertor 'cause like the button be enabled also if selected index = 0 so it implementd very simply
namespace MCSearchMVVM
{
class MCBindButtonToComboBox : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return false;
return true;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{ throw new NotImplementedException(); }
}
}
Now to the real stuff ;)
Little advice before that is I like allways put the view(.xaml file) and the vm(.cs file) on the same folder, that why i find this example very fast lol
First we begon with the view:
<UserControl x:Class="MCSearchMVVM.AddFilePage"
...
xmlns:local="clr-namespace:MCSearchMVVM"
...>
<UserControl.Resources>
<local:MCBindButtonToComboBox x:Key="enableCon"/>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
...
</Grid.RowDefinitions>
<Grid.Background>
...
</Grid.Background>
<Button Content="Browse.."
...
Command="{Binding BrowseCommand}"
IsEnabled="{Binding FileKindIndexSelected,
Converter={StaticResource enableCon}}"
.../>
<ComboBox ... SelectedIndex="{Binding FileKindIndexSelected, Mode=TwoWay}" ... >
...
</ComboBox>
...
</Grid>
Now the ViewModel :
public class AddFileViewModel : ObservableObject, IPageViewModel
{
...
private int _fileKindIndexSelected;
public int FileKindIndexSelected
{
get { return _fileKindIndexSelected; }
set { SetField(ref _fileKindIndexSelected, value, "FileKindIndexSelected");}
}
...
}
And the SetField func
public abstract class ObservableObject : INotifyPropertyChanged
{
[Conditional("DEBUG")]
[DebuggerStepThrough]
public virtual void VerifyPropertyName(string propertyName)
{
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#region INotifyPropertyChanged
public virtual void RaisePropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
OnPropertyChanged(propertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
protected bool SetField<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion // INotifyPropertyChanged
}
}
I Hope that direction was helpfull..
And sorry for my bad English =))

Visibility type-converter not being called

I have a test WPF Window with the below XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wpfApplication2="clr-namespace:WpfApplication2"
xmlns:test="clr-namespace:WpfApplication2.Properties"
DataContext="{Binding Path=TestClass}"
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<wpfApplication2:TestTypeConverter x:Key="TestConverter"/>
</Window.Resources>
<Grid>
<Grid Visibility="{Binding TestProperty, Converter={StaticResource TestConverter}, ConverterParameter='nottest'}">
<Label Content="Test Label"></Label>
</Grid>
</Grid>
</Window>
I have a test type-converter class which is below:
using System;
using System.Globalization;
using System.Windows.Data;
namespace WpfApplication2
{
class TestTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var valueToTest = (string) value;
var parameterToCheck = (string) parameter;
return valueToTest == parameterToCheck ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
}
TestClass is below:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using WpfApplication2.Annotations;
namespace WpfApplication2
{
public class TestClass : INotifyPropertyChanged
{
public TestClass()
{
TestProperty = "test";
}
private string _testProperty;
public string TestProperty
{
get { return _testProperty; }
set
{
if (_testProperty == value)
{
return;
}
_testProperty = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
The visibility property isn't being affected by the type-converter, and the Convert method itself isn't even being called (I have placed a breakpoint which is not being hit).
What am I doing wrong?
Thanks
Your binding seems wrong:
Visibility="{Binding 'test', Converter={StaticResource TestConverter}, ConverterParameter='nottest'}"
change it to:
Visibility="{Binding test, Converter={StaticResource TestConverter}, ConverterParameter='nottest'}"
If the property test does not exist, no converter will be called
Create a resource for the converter parameter (as shown in the snippet below) and use the resource as converter parameter instead of the literal
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication2="clr-namespace:WpfApplication2"
xmlns:test="clr-namespace:WpfApplication2.Properties"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
DataContext="{Binding Path=TestClass}"
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<wpfApplication2:TestTypeConverter x:Key="TestConverter"/>
<sys:String x:Key="converterParam">nottest</sys:String>
</Window.Resources>
<Grid>
<Grid Visibility="{Binding TestProperty, Converter={StaticResource TestConverter}, ConverterParameter={StaticResource converterParam}">
<Label Content="Test Label"></Label>
</Grid>
</Grid>
</Window>
Just omit the name of property altogether if you do not have a datacontext and it will work, The following wroked for me.
Visibility="{Binding Converter={StaticResource myTestConverter}}"
// see how Converter keyword is followed by Binding keyword and I did not specify property name after Binding keyword.

Adding a TextBlock before another element in a ListBox

I'm currently learning how to develop and building an app for windows phone 7.
If a certain value is true, I need to add a TextBlock to the ListBox before a TextBlock (say its name is x:Name="dayTxtBx").
I am currently using
dayListBox.Items.Add(dayTxtBx);
to add the text box.
Any help very much appreciated!
Thanks
This is pretty easy to do if you're using a DataTemplate and a ValueConverter and passing the whole object into the ListBox (rather than just a string). Assuming you have some object that looks like:
public class SomeObject: INotifyPropertyChanged
{
private bool mTestValue;
public bool TestValue
{
get {return mTestValue;}
set {mTestValue = value; NotifyPropertyChanged("TestValue");}
}
private string mSomeText;
public string SomeText
{
get {return mSomeText;}
set {mSomeText = value; NotifyPropertyChanged("SomeText");}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string name)
{
if ((name != null) && (PropertyChanged != null))
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
You can make a converter that looks like:
public class BooleanVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && (bool)value)
return Visibility.Visible;
else
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And add the converter to your XAML like so:
<UserControl x:Class="MyProject.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyProject">
<UserControl.Resources>
<local:BooleanVisibilityConverter x:Key="BoolVisibilityConverter" />
<UserControl.Resources>
Then you could have the ListBox defined in XAML like so:
<Listbox>
<Listbox.ItemTemplate>
<DataTemplate>
<StackPanel Orentation="Horizontal" >
<TextBlock Text="Only Show If Value is True" Visibility={Binding TestValue, Converter={StaticResource BoolVisibilityConverter}} />
<TextBlock Text="{Binding SomeText}" />
</StackPanel>
</DataTemplate>
</Listbox.ItemTemplate>
</Listbox>
Might seem like a lot, but it's really pretty simple once you get started. A great way to learn more about data binding and converters is at Jesse Liberty's blog ( http://jesseliberty.com/?s=Windows+Phone+From+Scratch ).

Categories

Resources