使用ViewModel中的多个变量绑定WPF控件可见性

时间:2015-04-30 17:32:04

标签: c# wpf xaml

我正在编写一个WPF用户控件,它显示一个包含多个页面的动态生成的TabControl,每个页面依次包含一个动态生成的控件列表(TextBox,Checkbox等)。

我想根据用户是否有权查看它们来设置TextBox,CheckBox控件的可见性。此权限是每个控件ViewModel(' VisiblyBy')上的值的组合,也是整个UserControl ViewModel(' UserRole')的属性的组合。我刚刚开始使用WPF,但标准方法似乎是使用ValueConvertor - 但我不明白我如何编写一个可以组合/访问不同属性(VisiblyBy和UserRole)的方法在我的ViewModel文件中存在于不同级别。

以下是我绑定到ViewModel的XAML的一部分:



<TabControl ItemsSource="{Binding VariableData.Pages}" SelectedIndex="0">
<!-- this is the header template-->
   <TabControl.ItemTemplate>
  <DataTemplate>
     <TextBlock Text="{Binding Title}" FontWeight="Bold"/>
  </DataTemplate>
</TabControl.ItemTemplate>
            
<!-- this is the tab content template-->
   <TabControl.ContentTemplate>
  <DataTemplate>
     <StackPanel>
        <ListBox  Grid.IsSharedSizeScope="True" 
                  ItemsSource="{Binding Variables}"
                  ItemTemplateSelector="{StaticResource templateSelector}">
        </ListBox>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
           <Button Content="Cancel" />
               <Button Content="Submit" 
                       Command="{Binding DataContext.CommitChangesCommand, 
                                   RelativeSource={RelativeSource FindAncestor, 
                                   AncestorType={x:Type TabControl}}}" />
        </StackPanel>
    </StackPanel>
</DataTemplate>
  </TabControl.ContentTemplate>
</TabControl>
&#13;
&#13;
&#13;

我还需要扩展控制未来可见性的变量数量,因为它还取决于使用它的应用程序的位置。

1 个答案:

答案 0 :(得分:9)

您可以尝试使用IMultiValueConverter并使用Multibinding。

<Window x:Class="ItemsControl_Learning.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ItemsControl_Learning"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:VisibilityConverter x:Key="conv" />
</Window.Resources>
<Grid>
    <Button Content="Test">
        <Button.Visibility>
            <MultiBinding Converter="{StaticResource conv}">
                <Binding  Path="Role" />
                <Binding Path="OtherProp" />                   
            </MultiBinding>
        </Button.Visibility>
    </Button>
</Grid>

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }       
}

class MainViewModel
{
    private string role;
    public string Role
    {
        get { return role; }
        set { role = value; }
    }

    private string otherProp;
    public string OtherProp
    {
        get { return otherProp; }
        set { otherProp = value; }
    }
    public MainViewModel()
    {
        Role = "Admin";
        OtherProp = "Fail";
    }
}

class VisibilityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values[0].ToString().Equals("Admin") && values[1].ToString().Equals("Pass"))
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Convert(...)方法中,values数组中不同输入的顺序与MultiBinding.Bindings集合中的顺序相同。

在此示例中,values[0]包含Role属性,values[1]将包含OtherProp,因为这是他们在XAML中插入的顺序