WPF:在ViewModel上使用略有不同的调用重用控件?

时间:2015-02-09 10:20:53

标签: c# wpf xaml

我有一个控件,ActionRequiredControl.xaml,它包含一个包含枚举列表的组合框。此控件具有ActionRequiredViewModel作为其DataContext,并且以下调用用于填充组合框:

    public IEnumerable<ActionType> Actions
    {
        get
        {
            return Enum.GetValues(typeof(ActionType)).Cast<ActionType>();
        }
    }

组合框如下。

   <StackPanel Orientation="Vertical">
   <Label>Action:</Label>
   <ComboBox Width="170" MinHeight="45"  Margin="5,0,5,5" Padding="5" 
             SelectedItem="{Binding Action, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
             ItemsSource="{Binding Actions, Mode=OneTime}" 
             VerticalContentAlignment="Center" IsEnabled="{Binding IsUsed}"/>
   </StackPanel>

此控件目前在两个地方使用(除了组合框之外还有更多) - 但是,我想在第三个地方重新使用它,只有#34;动作&#34;函数返回不同的列表。

最好的方法是什么?我唯一能想到的是创建一个继承自ActionRequiredViewModel的新类并重写Actions方法。

2 个答案:

答案 0 :(得分:0)

最简单的解决方案就是我在问题中指出的那个 - 我创建了一个继承自ActionRequiredViewModel的新类,并覆盖了&#34; Actions&#34;返回不同枚举列表的方法。

答案 1 :(得分:0)

是的,创建一个额外的ViewModel将是最简单的解决方案。 我不久前处于类似的情况,我的第一个实现(使用MVVM灯)使用两个VM,并在ViewModelLocator中注册并为每个VM提供一个属性:

SimpleIoc.Default.Register<ViewModel1>();
SimpleIoc.Default.Register<ViewModel2>();

public ViewModel ViewModel1Instance
{
    get
    {
        return ServiceLocator.Current.GetInstance<ViewModel1>();
    }
}

public ViewModel ViewModel2Instance
{
    get
    {
       return ServiceLocator.Current.GetInstance<ViewModel2>();
    }
}

然后在XAML中:

<local:MyUserControl DataContext="{Binding ViewModel1Instance, 
    Source={StaticResource Locator}}" ...

但是,为了更加灵活,我稍后用另一个解决方案替换它,这提供了更好的自定义。

我根据您的要求玩了一下并找到了解决方案:

在用户控件后面的代码中创建依赖属性作为代理:

public static readonly DependencyProperty ComboBoxItemsProperty =
            DependencyProperty.Register("ComboBoxItems",
            typeof(IEnumerable<object>), typeof(TestUserControl));


public IEnumerable<object> ComboBoxItems
{
    get
    {
        return (IEnumerable<object>)GetValue(ComboBoxItemsProperty);
    }
    set
    {
        SetValue(ComboBoxItemsProperty, value);
    }
}

在用户控件的XAML中:

...ItemsSource="{Binding ComboBoxItems, Mode=OneWay, RelativeSource=
    {RelativeSource AncestorType={x:Type UserControl}}}"...

在主视图模型中:

public IEnumerable<object> Items
{
    get
    {
        return Enum.GetValues(typeof(ActionType)).Cast<object>();
    }
 }

在主XAML中:

<local:TestUserControl ComboBoxItems="{Binding DataContext.Items, 
    Mode=OneTime, 
    RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
</local:TestUserControl>

这对我有用,但使用object代替自定义类型并不是最优雅的解决方案。

PS:这是我对SO的第一个答案,(我的问题还没有...)。

由于我多年来使用SO作为我的提示和技巧的主要来源,我认为我可以尝试来回馈...

当然,我承认:尝试回答并不是学习新主题的最糟糕的方法(而且WPF对我来说还是比较新的,所以请不要责怪我一个不理想的答案: - )