Updating the source of a Listbox with a multibinding - c#

I'm trying to get a multi-bound listbox to call the convert back method when items inside it change. Specifically I have a datatemplate that maps each entry to a checkbox and I'd like the source to be updated whenever a box is checked.
<ListBox x:Name="listBoxEdit" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="100" >
<ListBox.ItemsSource>
<MultiBinding Converter="{StaticResource selectedLoadsConverter}" >
<Binding Path="AvailableLoads"/>
<Binding Path="CurrentUnit"/>
</MultiBinding>
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Item1}" IsChecked="{Binding Item2}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I know the problem lies in the fact that I'm binding to to the ItemsSource property which is never actually being updated by the checkbox changing, but I can't figure out a good way to push the updates up to the source.

Related

Force RadioButtons to only change if the bound value actually changes

I have a bit of a strange case. The issue is that I have 3 radiobuttons and they are binded to the EffectiveValue property of my viewmodel.
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="5,0,0,0">
<StackPanel.Visibility>
<MultiBinding Converter="{StaticResource MultiBoolToVisibilityHidden}">
<Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=telerik:RadListBoxItem}"/>
<Binding Path="Criterion.IsOverridable"/>
<Binding Path="DataContext.CanOverrideEvaluation" ElementName="ThisInformationControl"/>
</MultiBinding>
</StackPanel.Visibility>
<telerik:RadRadioButton Content="Y" IsChecked="{Binding EffectiveValue, Converter={StaticResource EnumToBool}, ConverterParameter={x:Static utilities:Ternary.TRUE}, Mode=OneWay}" Style="{StaticResource EmptyRadioButtonStyle}"
Command="{Binding OverrideValueCommand}" CommandParameter="{x:Static utilities:Ternary.TRUE}" Margin="2,1" Width="16" VerticalAlignment="Center"/>
<telerik:RadRadioButton Content="?" IsChecked="{Binding EffectiveValue, Converter={StaticResource EnumToBool}, ConverterParameter={x:Static utilities:Ternary.UNKNOWN}, Mode=OneWay}" Style="{StaticResource EmptyRadioButtonStyle}"
Command="{Binding OverrideValueCommand}" CommandParameter="{x:Static utilities:Ternary.UNKNOWN}" Margin="2,1" Width="16" VerticalAlignment="Center"/>
<telerik:RadRadioButton Content="N" IsChecked="{Binding EffectiveValue, Converter={StaticResource EnumToBool}, ConverterParameter={x:Static utilities:Ternary.FALSE}, Mode=OneWay}" Style="{StaticResource EmptyRadioButtonStyle}"
Command="{Binding OverrideValueCommand}" CommandParameter="{x:Static utilities:Ternary.FALSE}" Margin="2,1" Width="16" VerticalAlignment="Center"/>
</StackPanel>
The problem is this. Say my ViewModel Effective Value is 'Y'. I click the 'N' button. But then based on certain conditions, I do not actually set the EffectiveValue to 'N' and it remains 'Y'. The problem I am having is now the 'N' looks selected even though the viewmodel still says that the value is 'Y'. What can I do to make sure my radiobuttons strictly listen to the viewmodel's value?
My current workaround it to force a property changed on the effective value but I feel this is kind of a hack.
Thanks
I think the answer lies with your radio button bindings. Notice that you have them set to OneWay, but you said that based on certain conditions you keep the value as 'Y'. How does the WPF control know that you've rejected the UI change?
I suggest changing the binding Mode to TwoWay and maybe also include UpdateSourceTrigger=PropertyChanged in the bindings. Then your code behind and the UI can communicate "two ways" to each other about what the appropriate state of the radio button should be.

bind user control to contentcontrol validation rules not firing

I have many user controls and i have main window which contains a content control and list box when user select from list box i bound the selected user control to the content control the problem is when the user control bound for the first time the validation rules is appears but when user control bound for the second time the validation rules disappear what is the problem ?
here is the main window :
<Grid>
<ListBox x:Name="FormsListBox" Margin="0,5,0,5" Grid.Row="1" Grid.Column="0" Width="180" ItemsSource="{Binding Formlist}" SelectedItem="{Binding SelectedFormInfo}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="Resources/Capture.PNG" ></Image>
<TextBlock Text="{Binding Path=FormName}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Grid.Column="1" x:Name="MainStackPanel" >
<ContentControl Content="{Binding Path=SelectedFormInfo.MainForm}">
</ContentControl>
</StackPanel>
</Grid>
here is the sample of validation role in user control:
<StackPanel Width="315" Margin="20,0,10,0">
<TextBox x:Name="TxtWeaponNumber" Width="315">
<TextBox.Text>
<Binding Path="SelectedWeapon.weaponNumber" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged" ValidatesOnNotifyDataErrors="True"
ValidatesOnDataErrors="True" NotifyOnValidationError="True"
NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True">
<Binding.ValidationRules>
<validationRules:RequiredRule ValidatesOnTargetUpdated="True" ValidationStep="RawProposedValue" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
Note: MainForm in SelectedFormInfo contains thee selected user control
i set my user control in AdornerDecorator and the Validation did not disappear

How to bind properties of one ObservableCollection of ListView to properties of SelectedItem of another ListView?

So I have a few ListViews. The first is binded to ObservaleCollection<ComPort>. All properties of ComPort may take some predefined values. Other ListViews are responsible for that properties: they show all that possible (predefined) values and SelectedItem should be the current value of that property of ComPort from the first ObservaleCollection.
I can't attach images so here is an external picture, it would make the situation clean: http://i.stack.imgur.com/ZBRRx.png
<Window.Resources>
<ResourceDictionary x:Name="rd">
<l:ComPorts x:Key="vComPorts"/>
<l:SystemPorts x:Key="vSystemPorts"/>
<l:BaudRates x:Key="vBaudRate"/>
<l:Parities x:Key="vParities"/>
<l:DataBits x:Key="vDataBits"/>
<l:StopBits x:Key="vStopBits"/>
<l:Timeouts x:Key="vTimeouts"/>
<l:ComPort x:Key="vSelectedPort"/>
</ResourceDictionary>
</Window.Resources>
...
<ListView
Name="PortsList"
Grid.Row="1"
Grid.Column="0"
Margin="5"
VerticalAlignment="Stretch"
ItemsSource="{StaticResource vComPorts}"
DataContext="{StaticResource vComPorts}"
SelectedValuePath="PortName"
SelectedValue="{Binding ElementName=SystemPortsList, Path=SelectedItem.Value}"
SelectionChanged="PortsList_SelectionChanged"
MouseDoubleClick="PortsList_MouseDoubleClick">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox />
<TextBlock Margin="5,0,0,0" Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView
x:Name="SystemPortsList"
Margin="5"
VerticalAlignment="Stretch"
DataContext="{Binding Source={StaticResource vSelectedPort}}"
ItemsSource="{Binding Source={StaticResource vSystemPortsView}}"
SelectedItem="{Binding Source={StaticResource vSelectedPort}, Path=PortName}"
MouseEnter="SystemPortsList_Refresh"
MouseLeave="SystemPortsList_Refresh"
Grid.Row="1"
Grid.Column="1" SelectionChanged="SystemPortsList_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Name="tb" Margin="5,0,0,0" Text="{Binding Path=Name}" />
</StackPanel>
</ListView.ItemTemplate>
</ListView>
I've tried to make an instance of class ComPort for saving current value of selected item from the first ListView, but anyway I can't cope with it without help. How this task should be solved?
1) Instead of handling SelectionChanged on the PortsList ListView, bind your checkbox to the ListViewItemsPanel like so:
<CheckBox IsChecked={Binding IsSelected, RelativeSource=Parent/>
2) Add an x:Name to your first ListBox, say x:Name="ComPortLB";
3) Remove DataContext on SystemPortsList;
4) Fix SelectedItem on SystemPortsList like so:
SelectedValue="{Binding ElementName=ComPortLB, Path=SelectedValue.PortName}"
I haven't tested any of this code and I haven't done this kind of stuff for a while, so I apologize for errors, but it should get you closer. I've also had to make some assumptions about your classes since you don't provide enough information.

ComboBox.ItemTemplate not displaying selection properly

In the question c# wpf - cannot set both DisplayMemberPath and ItemTemplate, I have read that you can replace the DisplayMemberPath to combine multiple data items in a ComboBox.
I set up my Combobox using ItemTemplate and it is successfully populated. But when I select an item in my ComboBox, I get Data.MaterialNumber displayed instead of the actual text I selected.
MaterialNumbers is an ObservableCollection<>
Can someone tell me why my ComboBox is not displaying the item correctly after it is selected?
// Binding from my ViewModel, which retrieves material numbers correctly.
ObservableCollection<MaterialNumber> MaterialNumbers = GetMaterialNumbers();
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding MaterialNumbers}"
SelectedItem="{Binding MaterialNumber}"
Validation.Error="View_Validator" Validation.ErrorTemplate="{StaticResource ErrorTemplateBorder}"
IsEnabled="{Binding IsEnabled}" IsEditable="True" IsReadOnly="True" Margin="0,10,0,0">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}: {1}">
<Binding Path="Program.Name" />
<Binding Path="MaterialNumberString" />
<Binding UpdateSourceTrigger="PropertyChanged" />
<Binding NotifyOnValidationError="True" />
<Binding ValidatesOnDataErrors="True" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Thanks to this article http://www.shujaat.net/2010/08/wpf-editable-combobox-with-datatemplate.html, I was able to figure out why my ComboBox did not display correctly when an item was selected. It is because my ComboBox was set to IsEditable="True". Apparently, when using a ComboBox.ItemTemplate and having MultiBinding set, the ComboBox cannot determine which item to display so it displays the class instead.

Show multiple columns from database in one combobox

I want to show in one combobox content from two database columns. I would like to show "Name Surname" but I don't know how. I'm working in C# (.NET) using MVVM pattern. "Name" and "Surname" are fields from table "tblGuests".
Thanks in advance,
Vladimir
You could create an ItemTemplate for the ComboBox that binds to all the properties you want to show.
<ComboBox ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="10,0,0,0"/>
<TextBlock Text="{Binding Path=LastName}" Padding="10,0,0,0"/>
</StackPanel>
<DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You could even create a UserControl that can be re-used and use that:
<PersonView>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="10,0,0,0"/>
<TextBlock Text="{Binding Path=LastName}" Padding="10,0,0,0"/>
</StackPanel>
</PersonView>
<ComboBox ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<PersonView/>
<DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Keep a string list property in Viewmodel,
populate that property in a data loading method, by combining name and surname strings,
bind string property to combo box,
<ComboBox Name="ComboBox1" ItemsSource="{Binding YourStringListProperty}"/>
Another option could be to use MultiBinding something like this
<TextBlock Name="textBox2" DataContext="{StaticResource NameListData}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myNameConverter}"
ConverterParameter="FormatLastFirst">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
This code was taken directly from msdn. Refer to it for more details

Categories