I have a collection of Checkboxes in a Listbox binding to an Enum which uses a converter. Code shown below:
<ListBox HorizontalAlignment="Left" Height="183" Margin="159,30,0,0" VerticalAlignment="Top" Width="144">
<ListBox.Resources>
<local:FlagsEnumValueConverter x:Key="FlagsConverter" />
</ListBox.Resources>
<CheckBox Content="Checkbox1" IsChecked="{
Binding Path=TestModel.TestEnum,
Converter={StaticResource FlagsConverter},
ConverterParameter={x:Static tc:TestEnum.Test1}}"/>
<CheckBox Content="Checkbox2" IsChecked="{
Binding Path=TestModel.TestEnum,
Converter={StaticResource FlagsConverter},
ConverterParameter={x:Static tc:TestEnum.Test2}}"/>
<CheckBox Content="Checkbox3" IsChecked="{
Binding Path=TestModel.TestEnum,
Converter={StaticResource FlagsConverter},
ConverterParameter={x:Static tc:TestEnum.Test3}}"/>
</ListBox>
Converter Code:
class FlagsEnumValueConverter : IValueConverter
{
private int mTargetValue;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var mask = (int)parameter;
mTargetValue = (int)value;
return ((mask & mTargetValue) != 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
mTargetValue ^= (int)parameter;
return Enum.Parse(targetType, mTargetValue.ToString());
}
}
I'd rather use an ItemTemplate to keep things clean and simple however I'm not sure what to do with the 'ConverterParameter' since it requires the specific Enum value. I've been Googling for a solution but haven't found one. I honestly don't even know where to start. Is this even possible?
Related
I want to search in multiple fields in AutoCompleteBox, I want to search in ClientName if the user starts typing characters, and search in ClientNumber if the user starts typing numbers.
I searched on the internet and from this Answer I understand that I should use Converter to accomplish what I want, But unfortunately, they do not explain how can I write the converter!
This is the AutoCompleteBox
<toolkit:AutoCompleteBox x:Name="txbClientName" FilterMode="StartsWith" IsTextCompletionEnabled="True"
ItemsSource="{Binding ocClients}"
ValueMemberBinding="{Binding Converter= {StaticResource ClientSearch}}"
SelectedItem="{Binding ElementName=this,
Path=ContactPerson,
Mode=TwoWay,
UpdateSourceTrigger=LostFocus}" PreviewKeyUp="txbClientName_PreviewKeyUp" LostFocus="txbClientName_LostFocus">
<toolkit:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding ContactPerson}"/>
</StackPanel>
</DataTemplate>
</toolkit:AutoCompleteBox.ItemTemplate>
What should the ClientSearch Converter do ??
public class ClientSearchConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//What should I write here !!!
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
Any help, please!
I have the following ContentControl:
<ContentControl
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedEntry}">
<ContentControl.ContentTemplate>
<DataTemplate DataType="controls:HCITextListEntry">
<controls:MyCustomControl
Text="{Binding Text}"
Parameter="{Binding Parameters}"/>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
Everytime the SelectedEntry property changes, I want to redraw/reinit MyCustomControl. Actually only the properties are updated.
You may drop the ContentTemplate and write a converter for the Content Binding that returns a MyCustomControl instance:
<ContentControl Content="{Binding SelectedEntry,
RelativeSource={RelativeSource TemplatedParent},
Converter={StaticResource MyCustomControlConverter}}"/>
The converter:
public class MyCustomControlConverter : IValueConverter
{
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
var control = new MyCustomControl();
control.SetBinding(MyCustomControl.TextProperty,
new Binding("Text") { Source = value });
control.SetBinding(MyCustomControl.ParameterProperty,
new Binding("Parameters") { Source = value });
return control;
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
I have a "Checked ListBox", a ListBox with a CheckBox for each of my Items.
In this ListBox I have a List of Players.
<ListBox ItemsSource="{Binding MyPlayers}" SelectedItem="{Binding SelectedPlayer}" Margin="69,51,347.4,161.8">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem>
<CheckBox IsChecked="{Binding ???}" Content="{Binding Path=Pseudo}" />
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ViewModel :
public class MainWindowViewModel : BaseViewModel
{
SavingContext MyDatabaseContext;
public ObservableCollection<Player> MyPlayers
{
get
{
return MyDatabaseContext.MyPlayers.Local;
}
}
Tournament _MyTournament;
public Tournament MyTournament
{
get
{
return _MyTournament;
}
set
{
_MyTournament = value;
}
}
public MainWindowViewModel(Tournament myTournament)
{
MyDatabaseContext = new SavingContext();
MyDatabaseContext.MyPlayers.Load();
MyTournament = myTournament;
}
}
I pass in my ViewModel a Tournament, that contains an HashSet of Players called Participants.
I would like to bind my IsChecked properties to the result of MyTournament.Participants.Contains(this) with this being the Player related to the CheckBox. But I can't manage to make it works.
Edit :
I tried to use a Converter, but with no success.
<helper:PlayerToTournamentRegistered x:Key="PlayerToTournamentRegistered" />
<ListBoxItem>
<CheckBox IsChecked="{Binding Converter={StaticResource PlayerToTournamentRegistered}}" Content="{Binding Path=Pseudo}" />
</ListBoxItem>
public class PlayerToTournamentRegistered : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//Temp test to see if it would work
if (value == null) return false;
return true;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I get an error each time Provide value on 'System.Windows.Data.Binding' threw an exception
Any Advices ?
So I managed to get it working using a MultiConverter.
The first error that I had was due to the fact that the Mode is by Default Two Way, I only want to have my Converter work OneWay.
I used a MultiBinding to send to my Converter both my ListBoxItem and my Tournament.
My Converter return true or false, and is linked to my CheckBox.IsChecked properties.
List Box :
<ListBox ItemsSource="{Binding MyPlayers}" SelectedItem="{Binding SelectedPlayer}" Margin="69,51,347.4,161.8">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem>
<CheckBox Content="{Binding Path=Pseudo}" >
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource PlayerToTournamentRegistered}" Mode="OneWay">
<Binding />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Window}" Path="DataContext.MyTournament"/>
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Converter :
public class PlayerToTournamentRegistered : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if(!(values[0] is Student) || !(values[1] is Tournament))
{
return false;
}
Tournament myTournament = (Tournament)values[1];
Student myPlayer = (Student)values[0];
if (myTournament.Participants.Contains(myPlayer))
return true;
return false;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
I've a combobox, which allows me to select a type. When I select a type, i'm able to fill a component. But I'd like that my component corresponding to my type. So, if it's a date, i'd like to display a datepicker, and if it's a string, i'd like to display a textbox.
How can I do that ?
I don't want to change things around DataTemplate, because this row is a part of a datagrid :)
<DataGridTemplateColumn Header="SQLValue" Width="0.55*" CanUserResize="False" CanUserReorder="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- HERE ! HOW CAN I CHOOSE ONE BY A CONDITION ? -->
<DatePicker/>
<TextBox Text="{Binding SqlValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The idea here is: you should a property in data context call DispType (int)
Then in each control you binding Visibility with above property, include a Converter convert number to Visible or not, Converter have parameter is number.
You can see my eg:
<Grid>
<Button Visibility="{Binding DispType, Converter={StaticResource VisibilityTypeConverter}, ConverterParameter=1}"/>
<TextBox Visibility="{Binding DispType, Converter={StaticResource VisibilityTypeConverter}, ConverterParameter=2}"/>
<DatePickerTextBox Visibility="{Binding DispType, Converter={StaticResource VisibilityTypeConverter}, ConverterParameter=3}"/>
</Grid>
You see the hard code for ConverterParameter.
And Converter class
public class VisibilityTypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int actualType = parameter == null ? 0 : System.Convert.ToInt32(parameter);
int compareType = value == null ? 0 : System.Convert.ToInt32(value);
if (actualType == compareType)
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Please not that code is only demo, you should change code to meet your expectation.
I am trying to learn how to use IValueConverter. I have the following converter:
[ValueConversion(typeof(string), typeof(string))]
public class RequiredFieldConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "";
return value.ToString() + "*";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "";
var str = value.ToString();
return str+"Convert Back testing";
}
}
I have added the RequiredFieldConverter resource in my app.xaml file and I want to try it as:
<TextBox Name="textBox2" Width="120" />
<TextBox Text="{Binding ElementName=textBox2, Path=Text, Converter=RequiredFieldConverter}" Name="textBox3" Width="120" />
I was hoping that when I type "hello" in textbox2 it shows "hello*" in textbox3 but it does not work. In fact I get the following exception at runtime:
{"Unable to cast object of type 'System.String' to type 'System.Windows.Data.IValueConverter'."}
also I know that the value converter function is working because it works when I do:
Content="{Binding Source={StaticResource Cliente}, Converter={StaticResource RequiredFieldConverter}}"
... You are getting the error as it trying to interpret RequiredFieldConverter as an reference to an IValueConverter. You need to use a StaticResource or DynamicResource to reference the converter as you have done in your second example.
<TextBox Text="{Binding ElementName=textBox2, Path=Text, Converter={StaticResouce RequiredFieldConverter}}" Name="textBox3" Width="120" />