I'm trying to build a UserControl which includes 2 listBoxes. I then wan't to set the itemsSources for the listboxes where I use the UserControl.
As I understand that is what DependencyProperties
are for. However I'm not successful in doing this. I do believe it mostly has to do with the timing of initialization. Any pointer on what I'm doing right, how I can make it better and such is welcome.
Here is my user control, I'm learning as I'm going so I guess I could do it better
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<ListBox Name="SET" ItemsSource="{Binding Path=SetCollection}" />
<UniformGrid Rows="4" Grid.Column="1">
<Grid />
<Button Margin="10" Click="selectionBtnClick">--></Button>
<Button Margin="10" Click="removeBtnClick">Remove</Button>
</UniformGrid>
<ListBox Name="SUBSET" ItemsSource="{Binding Path=SubsetCollection}" Grid.Column="2" />
</Grid>
CodeBehind
public partial class SubsetSelectionLists : UserControl
{
public static DependencyProperty SetCollectionProperty = DependencyProperty.Register("SetCollection", typeof(CollectionView), typeof(SubsetSelectionLists));
public static DependencyProperty SubsetCollectionProperty = DependencyProperty.Register("SubsetCollection", typeof(CollectionView), typeof(SubsetSelectionLists));
public CollectionView SetCollection
{
get
{
return (CollectionView) GetValue(SetCollectionProperty);
}
set
{
SetValue(SetCollectionProperty, value);
}
}
public CollectionView SubsetCollection
{
get
{
return (CollectionView)GetValue(SubsetCollectionProperty);
}
set
{
SetValue(SubsetCollectionProperty,开发者_开发知识库 value);
}
}
public SubsetSelectionLists()
{
InitializeComponent();
}
private void selectionBtnClick(object sender, RoutedEventArgs e)
{
SUBSET.Items.Add(SET.SelectedItem);
}
private void removeBtnClick(object sender, RoutedEventArgs e)
{
SUBSET.Items.Remove(SUBSET.SelectedItem);
}
}
And the code behind where I use it
public partial class SomeWindow : Window
{
ViewModel vm = new ViewModel();
public SomeWindow()
{
InitializeComponent();
NameOfUserControl.SetCollection = vm.InputView;
NameOfUserControl.SubsetCollection = vm.OutputView;
}
}
Here the SetCollection is set as inputView and then later tied to the DependencyProperty severing the original binding I think. Any idea where I'm going wrong?
Ps. subquestion - As I will be moving from one collection to the other shouldn't I ensure somehow that the collection hold objects off the same type? How could I do that?
First of all you should set the DataContext
property in SomeWindow to vm. This will allow very simple binding expression in your SomeWindow.xaml.
public partial class SomeWindow : Window
{
ViewModel vm = new ViewModel();
public SomeWindow()
{
InitializeComponent();
this.DataContext = vm;
}
}
In SomeWindow.xaml:
<local:SubsetSelectionLists
SetCollection="{Binding Path=InputView}"
SubsetCollection ="{Binding Path=OutputView}" />
There are several ways to solve the binding problem in the user control:
Setting the data context
Add the following to the constructor of the user control.
this.DataContext = this;
Wpf binds against the current data context, unless a specific source (e.g. ElementName) has been set.
Use binding with ElementName
You could reference the user control in the binding expressions.
<UserControl x:Class="WpfApplication1.SubsetSelectionLists"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root">
<Grid>
...
<ListBox Name="SET"
ItemsSource="{Binding Path=SetCollection, ElementName=root}" />
...
<ListBox Name="SUBSET" Grid.Column="2"
ItemsSource="{Binding Path=SubsetCollection, ElementName=root}" />
</Grid>
</UserControl>
Bind to the VM
Another method would be to set the data context of the user control in SomeWindow and bind to the Properties of the VM. You could then remove the dependency properties of the user control.
public partial class SomeWindow : Window
{
ViewModel vm = new ViewModel();
//with properties InputView and OutputView
public SomeWindow()
{
InitializeComponent();
NameOfUserControl.DataContext = vm;
}
}
In the user control:
<Grid>
...
<ListBox Name="SET"
ItemsSource="{Binding Path=InputView}" />
...
<ListBox Name="SUBSET" Grid.Column="2"
ItemsSource="{Binding Path=OutputView}" />
</Grid>
精彩评论