13

I have a TabControl with six tabs in my ResultView. The ViewModel that sits behind this View can be either a ResultTypeOneViewModel or ResultTypeTwoViewModel, each of which derives from ResultViewModel but you can interchangeably use the result viewer with either result type.

The difference is that in ResultTypeOneViewModel, tabs 1 & 3 need to be visible and the rest hidden. In ResultTypeTwoViewModel, tabs 2, 3, 4, 5, 6 need to be visible and tab 1 hidden.

I wanted to do this via something like

<TabItem Name="1" Visibility={Binding IsTabVisible(0)}>
<TabItem Name="2" Visibility={Binding IsTabVisible(1)}>
<TabItem Name="3" Visibility={Binding IsTabVisible(2)}>
etc...

And have an abstract method declaration in ResultsViewModel such as

public abstract Visibility IsTabVisible(int index);

And in ResultsOneViewModel have

public override Visibility IsTabVisible(int index)
{
    if (index == 0 || index == 2) return Visibility.Visible;
    return Visibility.Hidden;
}

And in ResultsTwoViewModel have

public override Visibility IsTabVisible(int index)
{
    if (index == 0) return Visibility.Hidden;
    return Visibility.Visible;
}

But I cannot figure out how to call a method like this with a parameter through bindings iN WPF XAML.

Can anyone suggest how I can do this or if it's not possible via this method, another way I could solve this problem?

4

3 回答 3

12

要直接回答您的问题,您可以使用ObjectDataProvider为您调用一个方法,以便您可以使用结果:

xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:Windows="clr-namespace:System.Windows;assembly=PresentationCore"

...

<Window.Resources>
    <ObjectDataProvider x:Key="IsTab1VisibleMethod" 
        ObjectType="{x:Type Windows:Visibility}" IsAsynchronous="True" 
        MethodName="IsTabVisible">
        <ObjectDataProvider.MethodParameters>
            <System:Int32>0</System:Int32>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

然后您应该能够像这样访问结果(但您需要为每个结果之一TabItem):

<TabItem Visibility="{Binding Source={StaticResource IsTab1VisibleMethod}}" />

Visibility但是,在代码中操作 UI 属性通常不是一个好习惯,因此更好的做法是使用@Highcore 建议BooleanToVisibilityConverterBind属性Visibility值。您可以在 StackOverflow 上的Binding a Button Visibility to bool value in ViewModelbool中看到一个示例。

在我看来,更好的解决方案是简单地为每个视图模型提供一个视图。

于 2013-11-14T15:01:09.207 回答
3

对这个问题的一个更好的建议是在 TabItem 的样式中使用 style.DataTrigger,如下所示:

<TabItem>
    <TabItem.Style>
        <Style target="{x:Type TabItem}">
            <Style.DataTriggers>
                <DataTrigger Binding="{Binding IsTabVisible}" Value="False">
                    <Setter Property="Visibility" Value = "Collapsed"/>
                </DataTrigger>
            </Style.DataTrigers>
        </Style>
    <TabItem.Style>
</TabItem>
于 2014-07-02T11:02:54.920 回答
2

您可以使用索引器属性将单个参数传递给属性。虽然从索引器属性返回布尔值可能不是很直观,但它对我来说很好用。另请记住,索引器属性失去了预期的功能。

    class MyClass
    {
        public bool this[int tabNumber]
        {
            get
            {
                // Do logic to determine visibility here or in a separate method
                return IsTabVisible(tabNumber);
            }
        }

        bool IsTabVisible(int tabNumber)
        {
            bool result;

            // Method logic...

            return result;
        }
    }

因此,在 XAML 中,您可以使用类名并在方括号之间提供参数。

<TabItem Visibility="{Binding MyClass[0]}}"/>

如果您需要为索引器属性设置 NotifyPropertyChanged,请使用:

    NotifyPropertyChanged("Item[]");

我不知道这是否适合 MVVM 模式,但它可能对任何想要绑定到具有单个参数的方法的人有用。

于 2020-01-14T10:42:41.183 回答