I've got a problem with a Combobox in a VSIX-Project. I'm using the MVVM-pattern.
<ComboBox
ItemsSource="{Binding ProjectList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name"
IsSynchronizedWithCurrentItem="True"
Style="{StaticResource MyStyle}"
SelectedValue="{Binding Project, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
This is my Combobox which is bindet to a List of Projects. The SelectedValue is a project of the list. Like this:
ProjectList = New List(Of Project)(Helper.GetFormsProjects())
If ProjectList.Count > 0 Then
Project = ProjectList(0)
End If
But if I select another Value in the Combobox, it wouldn't call the setter of the project property.
Here are the properties:
Public Property _projectList As List(Of Project)
Public Property ProjectList As List(Of Project)
Get
Return _projectList
End Get
Set(value As List(Of Project))
_projectList = value
OnPropertyChanged()
End Set
End Property
Public Property _project As Project
Public Property Project As Project
Get
Return _project
End Get
Set(value As Project)
_project = value
OnPropertyChanged()
End Set
End Property
Related
I cant get how to do such simple thing as getting list of all checked items from WPF Toolkit's CheckComboBox.
View:
<xctk:CheckComboBox DisplayMemberPath="Name"
ItemsSource="{Binding RouteSheetRecordOperations, Mode=OneWay}"
SelectedItemsOverride="{Binding SelectedRouteSheetRecordOperations, Mode=OneWayToSource}" />
View model:
Public ReadOnly Property RouteSheetRecordOperations As New ObservableCollection(Of RouteSheetRecordOperation)
Property SelectedRouteSheetRecordOperations As List(Of RouteSheetRecordOperation)
Get
Return _selectedRouteSheetRecordOperations
End Get
Set
_selectedRouteSheetRecordOperations = Value
End Set
End Property
The main problem is that in setter of SelectedRouteSheetRecordOperations property, Value is ALWAYS Nothing (null).
Remove Mode=OneWayToSource from the Binding:
<xctk:CheckComboBox DisplayMemberPath="Name"
ItemsSource="{Binding RouteSheetRecordOperations, Mode=OneWay}"
SelectedItemsOverride="{Binding SelectedRouteSheetRecordOperations}" />
Also note that the setter of the SelectedRouteSheetRecordOperations property is not supposed to get hit when you select an item in the CheckComboBox. An item is supposed to be added to the source collection so you might as well remove the setter and you probably want to return an ObservableCollection(Of RouteSheetRecordOperation).
Also note that the property must be public.
Try this along with the above XAML markup:
Private _selectedRouteSheetRecordOperations As New ObservableCollection(Of RouteSheetRecordOperation)
Public ReadOnly Property SelectedRouteSheetRecordOperations As ObservableCollection(Of RouteSheetRecordOperation)
Get
Return _selectedRouteSheetRecordOperations
End Get
End Property
I am using Silverlight Application in that I am using Datagrid and binding Data based on Observable Collection, but when I am trying to Bind the Observable Collection to Dropdown it's not binding, do we need to write code to Bind in the xaml Code behind.
My Code :
<sdk:DataGridTemplateColumn Header="lab Validated?" CanUserSort="True">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<ComboBox Height="Auto" HorizontalAlignment="Left"
Name="cboLabValidated" VerticalAlignment="Center" Width="80"
ItemsSource="{Binding Path=LabValidatedList}">
</ComboBox>
</Grid>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
ViewModel :
Public LabValidatedList As New List(Of String)() From { _
"Yes", _
"No"
}
In order to be usable as the source of a binding, LabValidatedList has to be a public property, not a field:
Private labValidatedListValue As New List(Of String)() From { _
"Yes", _
"No"
}
Public Property LabValidatedList() As List(Of String)
Get
Return Me.labValidatedListValue
End Get
Set(ByVal value As List(Of String))
Me.labValidatedListValue = value
End Set
End Property
Sorry if the above does not compile immediately, but VB is not my language. Note also that a List(Ofd String) is not an ObservableCollection.
I want to use SelectedItem to set selection to a combobox from code.
I can only get it to work by using SelectedValue. SelectedItem will throw a null reference exception with this at the top of the stacktrace:
at AttachedCommandBehavior.CommandBehaviorBinding.Execute()
The XAML:
<Window x:Class="MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:acb="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ComboBox Name="ComboItems1"
DisplayMemberPath="Value"
SelectedValuePath="Key"
ItemsSource="{Binding Items}"
SelectedValue="{Binding SelectedValue}"
acb:CommandBehavior.Event="SelectionChanged"
acb:CommandBehavior.Command="{Binding Path=SelectionChangedCommand}"
acb:CommandBehavior.CommandParameter="{Binding ElementName=ComboItems1, Path=SelectedItem}" />
<ComboBox Name="ComboItems2"
DisplayMemberPath="Value"
SelectedValuePath="Key"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}"
acb:CommandBehavior.Event="SelectionChanged"
acb:CommandBehavior.Command="{Binding Path=SelectionChangedCommand}"
acb:CommandBehavior.CommandParameter="{Binding ElementName=ComboItems2, Path=SelectedItem}"/>
</StackPanel>
The code:
Imports AttachedCommandBehavior
Public Class MainWindowViewModel
Private _mainWindowView As MainWindowView
Public Property Items As New List(Of KeyValuePair(Of Integer, String))
Public Property SelectedItem As Nullable(Of KeyValuePair(Of Integer, String))
Public Property SelectedValue As Nullable(Of Integer)
Public Property SelectionChangedCommand As ICommand
Public Sub New()
Items.Add(New KeyValuePair(Of Integer, String)(1, "first item"))
Items.Add(New KeyValuePair(Of Integer, String)(2, "second item"))
Items.Add(New KeyValuePair(Of Integer, String)(3, "third item"))
Dim simpleCommand As SimpleCommand = New SimpleCommand()
simpleCommand.ExecuteDelegate = Sub(selectedItem As Object)
HandleSelectionChanged(selectedItem)
End Sub
SelectionChangedCommand = simpleCommand
SelectedValue = 1
'SelectedItem = Items(1) 'uncomment this to raise the null ref exception
End Sub
Private Sub HandleSelectionChanged(ByRef selectedItem As Object)
If selectedItem IsNot Nothing Then
'Do something
End If
End Sub
End Class
Why does selecteditem not work?
UPDATE:
Nikolay: you have a keen eye. That was due to last minute copy paste work!
Blindmeis: this, ofcourse, is an abstract from a much larger program in which I need the selectionchanged event to execute some actions. Those commandbindings have to stay (though maybe they need some fixing).
Regards,
Michel
why you have these commandbindings?
<ComboBox
DisplayMemberPath="Value"
SelectedValuePath="Key"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}" />
viewmodel
//this select the "third item" in your combobox
SelectedItem = Items[2];/dont know the vb indexer stuff ;)
this works.
Edit:
viewmodel
public KeyValuePair<int, string> SelectedItem
{
get{return this._selectedItem;}
set{
if(this._selectedItem==value)
return;//no selection change
//if you got here then there was a selection change
this._selectedItem=value;
this.OnPropertyChanged("SelectedItem");
//do all action you want here
//and you do not need selection changed event commmandbinding stuff
}
}
acb:CommandBehavior.CommandParameter="{Binding ElementName=ComboItems, Path=SelectedItem}"
You don't have element with name ComboItems, you have ComboItems1 and ComboItems2. I think this is the problem.
<ItemsControl ItemsSource="{Binding ExportFormat, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" Margin="5" Height="50" Width="70" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.setExportFormat, UpdateSourceTrigger=PropertyChanged}" CommandParameter="{Binding}"></Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
So i have that code in my xaml and the button gets filed with a list of string. Depending on what the users chooses on previous Usercontrol that item will be filed with differents items. The problem is if the user select one option at the first run the button will be filled correctly but if the user go back and select the other option the control doenst update and shows the same as before..
My english is not the best but i think i could made me understand! Any idea?!
PS: the bindind on Button is to a readOnly property so i cant define it to Mode="TwoWay".. i took a look on the debug and the property ExportFormat gets updates with the new items but the usercontrol still displays the first option!!
Sincerely Rui Nunes
You didn't provide code-behind so I'm gonna take a few shots in the dark here:
The ExportFormatcollection is not an ObservableCollection (or more generally, doesn't implement INotifyCollectionChanged).
If it actually is an ObservableCollection, you assign it directly, instead of clearing its items and adding the new ones. example:
ExportFormat = MyNewObsCollection; //Bad
ExportFormat.Clear();
foreach(var newItem in myNewObsCollection)
{
ExportFormat.Add(newItem); //Good
}
Side note: ExportFormat should be readonly
Thanks to #Baboon for giving me some lights on this problem. So the Solution to my problem is:
So my ExportFormat Property was defined as:
Private _ExportFormat As New List(Of String)
Public Property ExportFormat As List(Of String)
Get
Return _ExportFormat
End Get
Set(value As List(Of String))
_ExportFormat = value
NotifyPropertyChanged("ExportFormat")
End Set
End Property
and i just had to change the List(of String) to ObjectModel.ObservableCollection(Of String)..
Private _ExportFormat As New ObjectModel.ObservableCollection(Of String)
Public Property ExportFormat As ObjectModel.ObservableCollection(Of String)
Get
Return _ExportFormat
End Get
Set(value As ObjectModel.ObservableCollection(Of String))
_ExportFormat = value
NotifyPropertyChanged("ExportFormat")
End Set
End Property
And my problems got solved.. Thanks once again!
i have
<Grid Name="thisPage">
<TextBlock Name="tbtb" />
<ScrollViewer Name="sv4" Visibility="Hidden">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextChanged="TextBox_TextChanged"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
in the MainWindow.vb, i have
movieArray as ObservableCollection(of Movie)
For i As Integer = 0 To 5
Me.movieArray.Add(New Movie(i))
Next
Me.sv4.DataContext = Me.movieArray
Me.listBox5.DataContext = Me.movieArray
Private Sub TextBox_TextChanged(sender As System.Object, e As System.Windows.Controls.TextChangedEventArgs)
Me.tbtb.Text = ""
For Each m As Movie In movieArray
Me.tbtb.Text += p.Title.ToString + " ^ "
Next
End Sub
Class Movie
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Property Title As Integer
Get
Return Me._title
End Get
Set(value As Integer)
Me._title = value
If Not (value = _title) Then
Me._title= value
NotifyPropertyChanged("Title")
End If
End Set
End Property
for the next page i have,
<Grid Name="nextPage" Visibility="Hidden" >
<ListBox Name="listBox5" >
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ListBox>
</Grid >
To change pages i just toggle the visibility of thisPage and nextPage using back, next buttons.
IM not sure what im doing wrong as:-
listbox5 shows only the original values, not anything changed by
textboxes.
tbtb, however is able to update its values
I think the problem might be your 'Title' property setter.
I'm a C# guy, not a VB expert... but it would appear that NotifyPropertyChanged will never get called.
value = _title will always be true because you just set Me._title = value in the previous line of code. Thus you will never execute any of the code in your if statement.
Why are you using Textchanged evetn in two way binding you dont need kind of stuff. two way binding is directly bind values from your view to property and from property to view
so don't use textchanged event and try again. this will work.