我正在寻找一种在Silverlight 4中创建UserControl并公开依赖属性的方法,该属性可以接受任何类型。我的意思是,例如,如果你看一下像AutoCompleteBox这样的标准silverlight控件,它就能够处理任何类型的集合。因此,您可以使用IEnumerable<Human> or IENumerable<Animal>
等绑定AutoCompleteBox。当选择任何项时,AutoCompleteBox将通过SelectedItem依赖项属性返回选定的Human实例或Animal实例值。
我希望通过usercontrol实现类似的灵活性。我想公开2个依赖属性SuggestedItems和SelectedItem。哪个集合通过Binding通过此用户控件的使用者设置为SuggestedItems,让我们以IEnumerable<Car>
为例,我希望SelectedItem属性通过Binding将Car类型的实例发送回消费者。如果我使用IEnumerable<Boat>
,那么我需要使用SelectedItem返回Boat。
我试图通过使用以下使用MVVM的示例来实现它,但它无法正常工作。我正在寻找一些关于它应该如何设计的线索,我是在正确的道路上还是我必须彻底改变我的设计?
我创建了一个名为VehicleSelectorUserControl的UserControl,它有自己专用的ViewModel,名为VehicleSelectorViewModel,有两个proerties SuggestedItems,SelectedItem。
usercontrol在其代码隐藏中具有相应的Dependency属性,以将它们暴露给usercontrol的使用者。 UserControl XAML有一个ListBox,它绑定到VehicleSelectorViewModel的SuggestedItems属性。当用户进行选择时,设置VehicleSelectorViewModel SelectedItem,它们调用名为ItemSelected的委托来通知VehicleSelectorUserControl代码隐藏,然后设置SelectedItem依赖属性以使其可供消费者使用。
下面是来自VehicleSelectorUserControl.xaml.cs代码的代码。
private VehicleSelectorViewModel _TheViewModel;
public UserNameControl()
{
InitializeComponent();
_TheViewModel = Resources["TheViewModel"] as VehicleSelectorViewModel;
_TheViewModel.ItemSelected = OnItemSelected;
}
public IEnumerable<object> SuggestedItems
{
get { return (IEnumerable<object>)GetValue(SuggestedItemsProperty); }
set { SetValue(SuggestedItemsProperty, value); }
}
public static readonly DependencyProperty SuggestedItemsProperty =
DependencyProperty.Register("SuggestedItems", typeof(IEnumerable<object>), typeof(VehicleSelectorControl), new PropertyMetadata(OnSuggestedItemsSet));
private static void OnSuggestedItemsSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
_TheViewModel.SuggestedItems = e.NewValue;
}
public object SelectedItem
{
get { return (String) GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(VehicleSelectorControl), null);
private void OnItemSelected()
{
SelectedItem = _TheViewModel.SelectedItem;
}
其ViewModel VehicleSelectorViewModel代码
public Action ItemSelected { get; set; }
private dynamic _SelectedItem;
public dynamic SelectedItem
{
get { return _SelectedItem; }
set
{
if (value != _SelectedItem)
{
_SelectedItem = value;
NotifyPropertyChanged("SelectedItem");
if(ItemSelected != null) ItemSelected.Invoke();
}
}
}
private dynamic _SuggestedItems;
public dynamic SuggestedItems
{
get { return _SuggestedItems; }
set
{
if (value != _SuggestedItems)
{
_SuggestedItems = value;
NotifyPropertyChanged("SuggestedItems");
}
}
}
消费者的XAML看起来像(消费者有自己的ViewModel,负责提供SuggestedCars [IEnumerable<Car>
],SuggestedBoats [IEnumerable<Boat>
]。
<my:VehicleSelectorControl x:Name="MyCarSelectorControl"
SuggestedItems="{Binding SuggestedCars, Mode=TwoWay}"
SelectedItem="{Binding UserSelectedCar, Mode=TwoWay}" />
<my:VehicleSelectorControl x:Name="MyBoatSelectorControl"
SuggestedItems="{Binding SuggestedBoats, Mode=TwoWay}"
SelectedItem="{Binding UserSelectedBoat, Mode=TwoWay}" />