web-dev-qa-db-ja.com

ViewModelのポリモーフィズムを使用したXAMLのパラメーターを持つメソッドへのバインド

ResultViewに6つのタブがあるTabControlがあります。このビューの背後にあるViewModelは、ResultTypeOneViewModelまたはResultTypeTwoViewModelのいずれかであり、それぞれがResultViewModelから派生しますが、どちらの結果タイプでも結果ビューアーを交換して使用できます。

違いは、ResultTypeOneViewModelでは、タブ1と3を表示し、残りを非表示にする必要があることです。 ResultTypeTwoViewModelでは、タブ2、3、4、5、6を表示し、タブ1を非表示にする必要があります。

私はこれを次のような方法でやりたかった

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

そして、ResultsViewModelに次のような抽象メソッド宣言があります。

public abstract Visibility IsTabVisible(int index);

そしてResultsOneViewModelには

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

そしてResultsTwoViewModelには

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

しかし、バインディングiN WPF XAMLを介して、パラメーターを使用してこのようなメソッドを呼び出す方法を理解できません。

誰かが私がこれを行う方法を提案できますか、またはこの方法では不可能な場合は、この問題を解決できる別の方法を提案できますか?

11
NZJames

質問に直接答えるには、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ごとにこれらの1つが必要になります)。

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

ただし、コードでVisibilityなどのUIプロパティを操作することは一般的に適切ではないため、@ Highcoreが提案したように、BooleanToVisibilityConverterからBindVisibilityプロパティをbool値に使用することをお勧めします。この例は、 ViewModelのbool値へのボタンの可視性のバインド StackOverflowの投稿で確認できます。

私の意見では、さらに良い解決策は、すべてのビューモデルに1つのビューを提供することです。

10
Sheridan

この質問に対するより良い提案は、次のような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>
2
Enzojz

インデクサープロパティを使用して、単一のパラメーターをプロパティに渡すことができます。インデクサープロパティからブール値を返すことはおそらくあまり直感的ではありませんが、私にとっては問題なく機能します。また、インデクサープロパティは、期待される機能を失うことに注意してください。

    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パターンに適合するかどうかはわかりませんが、単一のパラメーターを使用してメソッドにバインドしたい人には役立つ可能性があります。

0
XLars