如何使用可以接受任何类型的依赖项属性创建silverlight 4 usercontrol

时间:2011-04-21 20:36:22

标签: silverlight generics types dependencies properties

我正在寻找一种在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}" />

0 个答案:

没有答案