问题
This is my project using WPF with Caliburn.Micro. In my view I have an ItemsControl that bound to a BindableCollection, in the coresponding ViewModel, of a record class (MemberVotes). The class just has two fields: MemberName and Vote. The ViewModel also has a second BindableCollection of type string (VoteOptions). The Handle method in the ViewModel loads the data into both BindableCollections. The MemberVotes is loaded from the database and the VoteOptions is loaded by adding a new string collection via code.
I am able to Display The MemberName and Vote in Textboxes with no problem, but I cannot get the ComboBox to bind the the collection of vote options. There are no error messages. The ComboBoxes are just empty.
How do I bind the ComboBoxes to the VoteOptions and then set the selected item for each ComboBox to the Vote?
Any help would be greatly appreciated.
The View (MemberVoteView):
<ItemsControl x:Name="MemberVotes">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox Text="{Binding MemberName}" Grid.Column="0" IsReadOnly="True" />
<ComboBox Grid.Column="1" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.MemberVoteView.VoteOptions}" />
<TextBox Grid.Column="2" Text="{Binding Vote}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The ViewModel (MemberVoteViewModel):
public BindableCollection<MemberVoteModel> MemberVotes { get; set; }
public BindableCollection<string> VoteOptions { get; set; }
public void Handle()
{
MemberVotes = new BindableCollection<MemberVoteModel>();
MemberVotes .AddRange(GetVotes());
VoteOptions = new BindableCollection<string>();
VoteOptions.AddRange( new string[] { "Y", "N", "NV", "E", "O"} );
}
回答1:
I hope I understood your question correctly. Your problem lies with the following line.
<ComboBox Grid.Column="1" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.MemberVoteView.VoteOptions}" />
The DataContext of the ItemsControl is your ViewModel. It doesn't have a property called MemberVoteView. What you needed to have instead was
<ComboBox Grid.Column="1" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.VoteOptions}" />
To set the SelectedItem to Vote, you need to bind the SelectedItem Property of ComboBox to MemberVotes.Vote.
For Example,
<ComboBox Grid.Column="1" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.VoteOptions}" SelectedItem="{Binding Vote}" />
回答2:
Caliburn.Micro
is all about conventions. If you set the Name
of the ComboBox
to "VoteOptions" and move the VoteOptions
property to the MemberVoteModel
class and also add a SelectedVoteOption
property (with this exact name) to this class, the following should work:
<DataTemplate>
<Grid cal:Bind.Model="{Binding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox x:Name="MemberName" Grid.Column="0" IsReadOnly="True" />
<ComboBox x:Name="VoteOptions" />
<TextBox Grid.Column="2" x:Name="SelectedVoteOption" />
</Grid>
</DataTemplate>
You should also consider renaming MemberVoteModel
to MemberVoteViewModel
(you'll have to come up with a different name or rename your current view model) and define a separate for view it. This would be the Caliburn.Micro
way of setting this up.
If you decide to keep the VoteOptions
property in your current view model class, you could bind to it using the built-in mechanisms like this:
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl}, Path=DataContext.VoteOptions}"
SelectedItem="{Binding SelectedVoteOption}"/>
来源:https://stackoverflow.com/questions/57897674/how-to-bind-combobox-inside-itemscontrol-with-caliburn-micro