ObservableCollection<T> not updating UI - wpf

I'm having an issue with an ObservableCollection getting new items but not reflecting those changes in a ListView. I have enough quirks in the way I'm implementing this that I'm having a hard time determining what the problem is.
My ObservableCollection is implemented thusly:
public class MessageList : ObservableCollection<LobbyMessage>
{
public MessageList(): base()
{
Add(new LobbyMessage() { Name = "System", Message = "Welcome!" });
}
}
I store the collection in a static property (so that its easily accessible from multiple user controls):
static public MessageList LobbyMessages { get; set; }
In the OnLoad event of my main NavigationWindow I have the following line:
ChatHelper.LobbyMessages = new MessageList();
My XAML in the UserControl where the ListView is located reads as:
<ListBox IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Mode=OneWay}"
x:Name="ListBoxChatMessages"
d:UseSampleData="True"
ItemTemplate="{DynamicResource MessageListTemplate}"
IsEnabled="True">
<ListBox.DataContext>
<Magrathea_Words_Tools:MessageList/>
</ListBox.DataContext>
</ListBox>
The initial message that I added in the constructor appears in the UI just fine.
Now, the way I add new items to the collection is from a CallBack coming from a WCF service. I had this code working in a WinForms application and it was neccessary to marshall the callback to the UI thread so I left that code in place. Here is an abbreviated version of the method:
Helper.Context = SynchronizationContext.Current;
#region IServiceMessageCallback Members
/// <summary>
/// Callback handler for when the service has a message for
/// this client
/// </summary>
/// <param name="serviceMessage"></param>
public void OnReceivedServiceMessage(ServiceMessage serviceMessage)
{
// This is being called from the WCF service on it's own thread so
// we have to marshall the call back to this thread.
SendOrPostCallback callback = delegate
{
switch (serviceMessage.MessageType)
{
case MessageType.ChatMessage:
ChatHelper.LobbyMessages.Add(
new LobbyMessage()
{
Name = serviceMessage.OriginatingPlayer.Name,
Message = serviceMessage.Message
});
break;
default:
break;
}
};
Helper.Context.Post(callback, null);
}
While debugging I can see the collection getting updated with messages from the service but the UI is not reflecting those additions.
Any ideas about what I'm missing to get the ListView to reflect those new items in the collection?

I resolved this issue.
Neither the static property or the context of the incoming data had anything to do with the issue (which seems obvious in hindsight).
The XAML which was generated from Expression Blend was not up to the task for some reason. All I did to get this to work was assign the ItemSource to the collection in C#.
ListBoxChatMessages.ItemsSource = ChatHelper.LobbyMessages.Messages;
My XAML is now more simplified.
<ListBox IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Mode=OneWay}" Background="#FF1F1F1F"
Margin="223,18.084,15.957,67.787" x:Name="ListBoxChatMessages"
ItemTemplate="{DynamicResource MessageListTemplate}"
IsEnabled="True"/>
I'm a little confused as to why this works. I was reading the MSDN articles on how to bind data in WPF and they included several binding objects, referencing properties on object, etc. I don't understand why they went to all the trouble when one line of code in the UserControl's constructor does the trick just fine.

You need to make your poco class within the ObservableCollection implement INotifyPropertyChanged.
Example:
<viewModels:LocationsViewModel x:Key="viewModel" />
.
.
.
<ListView
DataContext="{StaticResource viewModel}"
ItemsSource="{Binding Locations}"
IsItemClickEnabled="True"
ItemClick="GroupSection_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0,0,10,0" Style="{ThemeResource ListViewItemTextBlockStyle}" />
<TextBlock Text="{Binding Latitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding Longitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class LocationViewModel : BaseViewModel
{
ObservableCollection<Location> _locations = new ObservableCollection<Location>();
public ObservableCollection<Location> Locations
{
get
{
return _locations;
}
set
{
if (_locations != value)
{
_locations = value;
OnNotifyPropertyChanged();
}
}
}
}
public class Location : BaseViewModel
{
int _locationId = 0;
public int LocationId
{
get
{
return _locationId;
}
set
{
if (_locationId != value)
{
_locationId = value;
OnNotifyPropertyChanged();
}
}
}
string _name = null;
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
OnNotifyPropertyChanged();
}
}
}
float _latitude = 0;
public float Latitude
{
get
{
return _latitude;
}
set
{
if (_latitude != value)
{
_latitude = value;
OnNotifyPropertyChanged();
}
}
}
float _longitude = 0;
public float Longitude
{
get
{
return _longitude;
}
set
{
if (_longitude != value)
{
_longitude = value;
OnNotifyPropertyChanged();
}
}
}
}
public class BaseViewModel : INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
protected void OnNotifyPropertyChanged([CallerMemberName] string memberName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberName));
}
}
}

Related

WPF TextBox Binding ElementName null?

I have a ListBox control with TypeUsers.When I select some record in Listbox and update Name in TextBox the Name property/textbox return always null. Never take value from TextBox, always null ?
Image description here
This is my code
<ListBox x:Name="LstTypeUsers"
Grid.Row="0" Grid.Column="4"
Width="220" Height="120"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ItemsSource="{Binding TypeUsers}"
DisplayMemberPath="Name">
</ListBox>
<TextBox
Grid.Row="0" Grid.Column="2"
x:Name="txtName"
HorizontalAlignment="Left" Height="23"
TextWrapping="Wrap"
VerticalAlignment="Top" Width="170"
Text="{Binding ElementName=LstTypeUsers, Path=SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Validation.ErrorTemplate="{x:Null}"/>
<Button
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="100" Height="30"
Command="{Binding UpdateTypeUserCmd}"
Grid.ColumnSpan="3" Margin="20,90,0,0">
<StackPanel Orientation="Horizontal">
<Image Source="/Images/Save.png" />
<TextBlock Width="55" Height="18" ><Run Text=" "/><Run Text="Update"/></TextBlock>
</StackPanel>
</Button>
EDIT
// Model class
public class UserType: INotifyPropertyChanged
{
[Key]
private int usertypeId;
public int UserTypeId
{
get
{
return this.usertypeId;
}
set
{
this.usertypeId = value;
OnPropertyChanged("UserTypeId");
}
}
[MaxLength(200)]
private string name;
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
OnPropertyChanged("Name");
}
}
[Required]
private bool status;
public bool Status
{
get
{
return this.status;
}
set
{
this.status = value;
OnPropertyChanged("Status");
}
}
public virtual ObservableCollection<User> User { get; private set; }
public UserType()
{
this.User = new ObservableCollection<User>();
}
}
// ViewModelBase class
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// UserTypeViewModel
public class UserTypeViewModel
private UserType _userType;
private ObservableCollection<UserType> _UserTypeList;
// Constructor
public UserTypeViewModel()
{
_userType = new UserType();
_UserTypeList = new ObservableCollection<UserType>(GetUserTypeAll());
}
public ObservableCollection<TypeUsers> TypeUsers
{
get
{
return _UserTypeList;
}
set
{
_UserTypeList = value;
//OnPropertyChanged("TypeUsers");
}
}
public string Name
{
get
{
return _userType.Name;
}
set
{
_userType.Name = value;
//OnPropertyChanged("Name");
}
}
Thank you.
Implement INotifyPropertyChanged interface in UserType class.
You're binding directly to the WPF control (ListBox) and not the ViewModel. I suggest you add a property in your ViewModel that will bind to the TextBox.Text property, once the data changes or the user had changed the value in the TextBox, then the data will update and be reflected in the UI.
Also, if I remember correctly, at launch, the SelectedItem property of the ListBox is null, so there might be a problem there too, but I'm not certain about that...
I have resolved my problem. I have also implemented INotifyPropertyChanged interface in Model class. I'm new in WPF MVVM and I read that this interface is implemented only in the ViewModel for connection with View. Now I have implemented in both classes and everything works great.
Thanks Everyone.

ObservableCollection don't modify view

I have strange WPF ObservableCollection behavior. By unclear reason when collection modified and there is another condition in getter-method in some property of my class, it does't modify View. Although CollectionChanged event was invoked!
Without condition in getter method collection works good.
Too complicated and long-winded to explain here what I do in my work project. Therefore I make small simplify project and emulate same behavior. This project show you problem better then thousand words.
To see the problem - launch project as it is, looks how it works. It is really simple, 2 radiobuttons, datagrid and nothing else. Then go to the MainWindowViewModel, GridItems-property, uncomment commented code and launch project again. See the difference. When collection modify, get-method of GridItems-property dont't invoke (I check it with debugger). How not invoked method can make affect on something??? I don't have any idea on it. Help plz.
Project link:
http://www.megafileupload.com/en/file/443850/ObservableCollection-zip.html
class MainWindowViewModel : ViewModelBase
{
private ObservableCollection<GridItem> _totalStorage;
private ObservableCollection<GridItem> _gridItems;
public ObservableCollection<GridItem> GridItems
{
get
{
//if (_gridItems.Count == 0)
//{
// return _totalStorage;
//}
return _gridItems;
}
set
{
_gridItems = value;
RaisePropertyChanged("GridItems");
}
}
public MainWindowViewModel()
{
_totalStorage = new ObservableCollection<GridItem>();
_gridItems = new ObservableCollection<GridItem>();
GridItemsInit();
_gridItems.CollectionChanged += CollectionChanged;
}
/// <summary>
/// Collection change event handler
/// </summary>
/// <param name="o"></param>
/// <param name="e"></param>
private void CollectionChanged(object o, NotifyCollectionChangedEventArgs e)
{
}
private void GridItemsInit()
{
_totalStorage.Add(new GridItem
{
Name = "Igor",
LastName = "Balachtin",
FilerField = FileStatusEnum.All
});
_totalStorage.Add(new GridItem
{
Name = "Misha",
LastName = "Ivanov",
FilerField = FileStatusEnum.All
});
_totalStorage.Add(new GridItem
{
Name = "Ahmed",
LastName = "Magamed",
FilerField = FileStatusEnum.All
});
_totalStorage.Add(new GridItem
{
Name = "abrek",
LastName = "cheburek",
FilerField = FileStatusEnum.All
});
_totalStorage.Add(new GridItem
{
Name = "Irka",
LastName = "Dirka",
FilerField = FileStatusEnum.All
});
}
private void RefreshGridSource(string statusParam)
{
_gridItems.Clear();
//Если нажали на баттон new
if (statusParam.Equals(FileStatusEnum.All.ToString()))
{
foreach (var item in _totalStorage)
{
_gridItems.Add(item);
}
}
//Если нажали на archived
else if (statusParam.Equals(FileStatusEnum.Filtered.ToString()))
{
foreach (var item in _totalStorage.Where(g => g.FilerField == FileStatusEnum.Filtered))
{
_gridItems.Add(item);
}
}
}
private RelayCommand<object> _radioCommand;
public RelayCommand<object> RadioCommand
{
get { return _radioCommand ?? (_radioCommand = new RelayCommand<object>(HandlerFileRadio)); }
}
private void HandlerFileRadio(object obj)
{
if (obj == null)
return;
var statusParam = obj.ToString();
RefreshGridSource(statusParam);
}
}
Look at this sample.
//if (_gridItems.Count == 0)
//{
// return _totalStorage;
//}
Model:
public enum FileStatusEnum
{
All = 0,
Filtered
}
public class GridItem
{
public String Name { get; set; }
public String LastName { get; set; }
public FileStatusEnum FilerField
{
get; set;
}
}
Xaml:
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<RadioButton Margin="5" IsChecked="True" Command="{Binding RadioCommand}"
CommandParameter="All">All</RadioButton>
<RadioButton Margin="5" Command="{Binding RadioCommand}"
CommandParameter="Filtered">Filtered</RadioButton>
</StackPanel>
<DataGrid Grid.Column="1" ItemsSource="{Binding GridItems}" CanUserAddRows="False" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True" />
<DataGridTextColumn Header="LastName" Binding="{Binding LastName}" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
</Grid>
really better post all code here instead of link? :/
Once you are changing record after that your property is not Notifying.so please Notify after changing the collection.
Add below line in RefreshGridSource method after collection changed .
RaisePropertyChanged("GridItems");
Your GridItems property can return either _totalStorage or _gridItems depending upon a condition; _totalStorage and _gridSettings are two different instances of ObservableCollection. Initially, when _gridItems has no items, your GridItems property returns _totalStorage to WPF, and WPF listens on this instance for any CollectionChanged events.
In your RefreshGridSource method you are updating _gridItems (a differnt instance from _totalStorage), which WPF has no knowledge of.
But, when you rasie property changed for GridItems property from RefreshGridSource method WPF will re-read the property GridItems - this time, WPF gets _gridItems collection and it works as you expected.
Hope, I have explained well enough.

wpf binding combobox to observable collection

I have an ObservableCollection that gets it's data from a DataTable that is populate from a Postgres Database. I need to bind this ObservableCollection to a ComboBoxColumn in a DataGrid. I have seen quite a lot of examples on how to do this, yet I'm constantly missing something.
Edit: This is the new updated code and it is working except for the INotifyPropertyChanged that I have set only to "name" (yet)
namespace Country_namespace
{
public class CountryList : ObservableCollection<CountryName>
{
public CountryList():base()
{
// Make the DataTables and fill them
foreach(DataRow row in country.Rows)
{
Add(new CountryName((string)row.ItemArray[1], (int)row.ItemArray[0]));
}
}
}
public class CountryName: INotifyPropertyChanged
{
private string name;
private int id_country;
public event PropertyChangedEventHandler PropertyChanged;
public CountryName(string country_name, int id)
{
this.name = country_name;
this.id_country = id;
}
public string Name
{
get { return name; }
set {
name = value;
OnPropertyChanged("CountryName");
}
}
public int idcountry
{
get { return id_country; }
set { id_country = value; }
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
XAML:
xmlns:c="clr-namespace:Country_namespace"
<Windows.Resources>
<c:CountryList x:Key="CountryListData"/>
</Windows.Resources>
DataGrid Column:
<dg:DataGridTemplateColumn Header="country">
<dg:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource CountryListData}}" DisplayMemberPath="Name"></ComboBox>
</DataTemplate>
</dg:DataGridTemplateColumn.CellTemplate>
</dg:DataGridTemplateColumn>
first of all. you can just bind to public properties.
country_ seems no public property.
second if binding not work you always have to check datacontext first and binding path second. you can use Snoop to do this at runtime
EDIT:
you did not post your itemssource for your grid. so some assumptions here.
<DataGrid ItemsSource="{Binding MySource}">
...
<ComboBox ItemsSource="{Binding MySourcePropertyForCountries}"/>
--> this would work when your MySource object item has a public property MySourcePropertyForCountries.
but if your want to bind your combobox to a list wich is outside the MySource object. then you have to use some kind relativeSourcebinding or elementbinding.
<DataGrid x:Name="grd" ItemsSource="{Binding MySource}">
...
<ComboBox ItemsSource="{Binding ElementName=grd, Path=DataContext.MyCountries}"/>
--> this would work when the datacontext of the datagrid has a property MyCountries

IDataErrorInfo validation not triggered while using data template in UI

I am trying to build my application settings page depending on the properties exposed by ViewModel. I'm using .Net 4.0 with MVVM. ViewModel exposes single Collection of "group of setting values". Group represents properties that are dependent on each other and belong to a logical group wrt to domain. Settings page in view is created using DataTemplate like below:-
<DataTemplate x:Key="contentSettingGroup1">
<TextBlock Text="{Binding Field1Description}" />
<TextBox Text="{Binding Field1Value, Mode=TwoWay}" Grid.Column="2" />
<TextBlock Text="{Binding Field2Description}" />
<TextBox Text="{Binding Field2Value, Mode=TwoWay}" Grid.Column="6" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SettingGroup1}">
<HeaderedContentControl Header="{Binding}" HeaderTemplate="{StaticResource titleArea}" Content="{Binding}" ContentTemplate="{StaticResource contentSettingGroup1}" />
</DataTemplate>
Then I have a class in ViewModel module to represent the "Group of settings" as below:
public class SettingGroup1 : INotifyPropertyChanged, IDataErrorInfo
{
public double Field1value { get; private set; }
public double Field2value { get; private set; }
private double mField1;
public double Field1value
{
get { return mField1; }
set
{
if (mField1 != value)
{
mField1 = value;
RaisePropertyChanged(() => Field1value);
}
}
}
private double mField2;
public double Field2value
{
get { return mField2; }
set
{
if (mField2 != value)
{
mField2 = value;
RaisePropertyChanged(() => Field2value);
}
}
}
public string Error
{
get { return null; }
}
public string this[string property]
{
get
{
string errorMsg = null;
switch (property)
{
case "Field1value":
if (Field1value < 0.0)
{
errorMsg = "The entered value of Field1 is invalid !";
}
if (Field1value < Field2value)
{
errorMsg = "The Field1 should be greater than Field2 !";
}
break;
}
return errorMsg;
}
}
}
And finally the viewModel exposes collection of such group of settings:
public ObservableCollection<object> Settings
{
get
{
var pageContents = new ObservableCollection<object>();
var group1 = new SettingGroup1();
group1.Field1.Description = "Description value 1";
group1.Field1.Value = mValue1;
group1.Field2.Description = "Description value 2";
group1.Field2.Value = mValue2;
pageContents.Add(group1);
// add other groups of controls
// ...
return pageContents;
}
}
The Problem: The property setter is called but Data validation is not called whenever UI value is changed. I've tried putting IDataErrorInfo implementation in ViewModel class also but none works. I've to use group of settings as these application settings are used in many projects and we don't want duplicate XAML for each application.
Note: The viewmodel is not exposing the property that UI is binding to e.g. Field1Value but exposing an encapsulated object.
You aren't telling your view that the property you're binding to needs to be validated. Use "ValidatesOnDataErrors = true" in your binding.
<TextBox Text="{Binding Field1Value, Mode=TwoWay, ValidatesOnDataErrors=True}" Grid.Column="2" />

How to bind a ListBox to Properties in a Class?

I have one main outstanding issue, I know now how to databind to lists and individual items, but there is one more problem I have with this, I need to bind a listbox to some properties that are in a Class.
For Example I have two Properties that are bound in some XAML in a class called Display:
Public Property ShowEventStart() As Visibility
Public Property ShowEventEnd() As Visibility
I can use these in my XAML but I want them to be in a ListBox/Drop-down List, how can I have my properties show in this list and be able to change their values, does it have to be a List to be in a List?
I just want to be able to modify these properties from a Drop-down list to toggle the Visibility of the ShowEventStart and ShowEventEnd Property Values using the Checkboxes in the Drop-down List.
Plus this must be a Silverlight 3.0 solution, I cannot figure out how to have something that can be bound in the XAML which is not a list and then bound it as a list to modify these items!
I just need a list of Checkboxes which alter the values of the Class Properties such as ShowEventStart and ShowEventEnd, there are other properties but this will be a start.
You can create a PropertyWrapper class and in you window code behind expose a property that returns a List<PropertyWrapper> and bind your ListBox.ItemsSource to it.
public class PropertyWrapper
{
private readonly object target;
private readonly PropertyInfo property;
public PropertyWrapper(object target, PropertyInfo property)
{
this.target = target;
this.property = property;
}
public bool Value
{
get
{
return (bool) property.GetValue(target, null);
}
set
{
property.SetValue(target, value, null);
}
}
public PropertyInfo Property
{
get
{
return this.property;
}
}
}
your window code behind:
public partial class Window1 : Window, INotifyPropertyChanged
{
public Window1()
{
InitializeComponent();
properties = new List<PropertyWrapper>
{
new PropertyWrapper(this, typeof(Window1).GetProperty("A")),
new PropertyWrapper(this, typeof(Window1).GetProperty("B")),
};
this.DataContext = this;
}
private List<PropertyWrapper> properties;
public List<PropertyWrapper> Properties
{
get { return properties; }
}
private bool a;
private bool b = true;
public bool A
{
get
{
return a;
}
set
{
if (value != a)
{
a = value;
NotifyPropertyChange("A");
}
}
}
public bool B
{
get
{
return b;
}
set
{
if (value != b)
{
b = value;
NotifyPropertyChange("B");
}
}
}
protected void NotifyPropertyChange(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(
this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
your window markup:
<ListBox ItemsSource="{Binding Path=Properties}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Property.Name}"/>
<CheckBox IsChecked="{Binding Path=Value}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Hope this helps
I tried to mock up something similar. See how this works for you and let me know if I misunderstood the question.
From MainPage.xaml:
<StackPanel Orientation="Horizontal">
<ListBox SelectedItem="{Binding ShowControls, Mode=TwoWay}" x:Name="VisibilityList"/>
<Button Content="Test" Visibility="{Binding ShowControls}"/>
<CheckBox Content="Test 2" Visibility="{Binding ShowControls}"/>
</StackPanel>
The code behind MainPage.xaml.cs:
public partial class MainPage : UserControl
{
VisibilityData visibilityData = new VisibilityData();
public MainPage()
{
InitializeComponent();
VisibilityList.Items.Add(Visibility.Visible);
VisibilityList.Items.Add(Visibility.Collapsed);
this.DataContext = visibilityData;
}
}
And the data class:
public class VisibilityData : INotifyPropertyChanged
{
private Visibility showControls = Visibility.Visible;
public Visibility ShowControls
{
get { return showControls; }
set
{
showControls = value;
OnPropertyChanged("ShowControls");
}
}
private void OnPropertyChanged(string p)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
public event PropertyChangedEventHandler PropertyChanged;
}
When you run that code you should get a ListBox with the options Visible and Collapsed and when you choose an option you should see the visibility of the button and checkbox is changed to reflect your choice. Let me know if that's not what you were looking for.
After thinking about this the solution occured to me, which is to construct the List in XAML then using a Converter on the Checkboxes to convert their Boolean IsChecked to the Property Visibility Property in the Class.
You can create a list such as:
<ComboBox Canvas.Left="6" Canvas.Top="69" Width="274" Height="25" Name="Display">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=Display.EventStart,Mode=TwoWay,Converter={StaticResource VisibilityConverter}}"/>
<TextBlock Text="Event Start"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=Display.EventEnd,Mode=TwoWay,Converter={StaticResource VisibilityConverter}}"/>
<TextBlock Text="Event End"/>
</StackPanel>
</ComboBox>
I can then Bind to the Two Properties I want (this example from the actual application).

Resources