Binding to a method with parameter in XAML using polymorphism in ViewModel

后端 未结 3 1876
花落未央
花落未央 2021-02-20 09:34

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 deri

相关标签:
3条回答
  • 2021-02-20 09:47

    You can use an indexer property to be able to pass a single parameter to a property. Although it's probably not very intuitive to return a boolean value from an indexer property it works fine for me. Also keep in mind the indexer property looses it's expected functionality.

        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;
            }
        }
    

    So in XAML you can use the class name and provide a parameter between square brackets.

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

    If you need to raise a NotifyPropertyChanged for the indexer property use:

        NotifyPropertyChanged("Item[]");
    

    I don't know if this fits into the MVVM pattern but it could be useful for anyone who wants to bind to a method with a single parameter.

    0 讨论(0)
  • 2021-02-20 09:58

    A better suggestion to this question is to use style.DataTrigger in style of TabItem like this:

    <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>
    
    0 讨论(0)
  • 2021-02-20 10:00

    To answer your question directly, you can use the ObjectDataProvider to call a method for you so you can work with the results:

    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>
    

    You should then be able to access the result like this (but you'd need one of these for each TabItem):

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

    However, it's generally not good practice to manipulate UI properties such as Visibility in code, so a better idea would be to use a BooleanToVisibilityConverter to Bind the Visibility properties to bool values as @Highcore suggested. You can see an example of this in the Binding a Button Visibility to bool value in ViewModel post here on StackOverflow.

    In my opinion, an even better solution would be to simply provide one view for every view model.

    0 讨论(0)
提交回复
热议问题