首页 > 解决方案 > 具有多个用户控件级别的属性的 WPF 绑定

问题描述

我有两个用户控件(LoginView.xaml 和 DashboardView.xaml)。DashboardView.xaml 放置在 LoginView.xaml 中。现在,我的目标最初是 DashboardView 应该是不可见的,登录成功后它应该是可见的,并且堆栈面板“loginSP”中的控件应该是不可见的。

LoginView.xaml 如下:-

<UserControl x:Class="DashboardModule.LoginView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:DashboardModule"
         xmlns:converter="clr-namespace:Matrix.Infrastructure.Framework.Utility;assembly=Matrix.Infrastructure"
         mc:Ignorable="d" 
         x:Name="loginUC"
         d:DesignHeight="450" d:DesignWidth="800"  Background="Pink">
<UserControl.Resources>
    <ResourceDictionary>
        <converter:BooleanToVisibilityConverter x:Key="BoolVisibilityConverter"></converter:BooleanToVisibilityConverter>
    </ResourceDictionary>
</UserControl.Resources>
<StackPanel Margin="200">
    <StackPanel x:Name="loginSP">
        <TextBlock Text="Dashboard" ></TextBlock>
        <TextBox x:Name="tbUserName" Height="25" Width="300" ></TextBox>
        <PasswordBox Margin="2"></PasswordBox>
        <Button Content="Login" Command="{Binding LoginCommand}" CommandParameter="{Binding Path=Text,ElementName=tbUserName}"  Width="200"
            ></Button>
    </StackPanel>       

    <ContentControl>
        <ContentControl.Template>
            <ControlTemplate TargetType="{x:Type ContentControl}">
                <Grid>
                    <Border >
                        <ContentPresenter/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </ContentControl.Template>
        <local:DashboardView  Visibility="{Binding DashboardVisible, Converter={StaticResource BoolVisibilityConverter}}"/>
    </ContentControl>       

</StackPanel>

DashboardView.xaml 如下:-

<UserControl x:Class="DashboardModule.DashboardView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:DashboardModule"
         xmlns:converter="clr-namespace:Matrix.Infrastructure.Framework.Utility;assembly=Matrix.Infrastructure"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800" Background="BlanchedAlmond" x:Name="DashboardUC"
         Visibility="{Binding Visibility,ElementName=rootGrd}">
<UserControl.Resources>
    <ResourceDictionary>
        <converter:BooleanToVisibilityConverter x:Key="BoolVisibilityConverter"></converter:BooleanToVisibilityConverter>
    </ResourceDictionary>
</UserControl.Resources>
<Grid  x:Name="rootGrd" ToolTip="{Binding MyName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
       Visibility="{Binding DashboardVisible,Converter={StaticResource BoolVisibilityConverter}}">
    <TextBlock Text="{Binding MyName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"></TextBlock>          
</Grid>

我的 LoginViewModel.cs 如下:-

private readonly IEventAggregator eventAggregator;
    public DelegateCommand<string> LoginCommand { get; set; }           
    public DashboardViewModel DashborardVM { get; set; }
    public LoginViewModel(IEventAggregator eventAggregator)
    {
        this.eventAggregator = eventAggregator;
        DashborardVM = new DashboardViewModel();
        LoginCommand = new DelegateCommand<string>(Login, IsValid);
    }

    private void Login(string obj)
    {
        DashborardVM.MyName = "My Name After Login";
        DashborardVM.DashboardVisible = true;
        //this.eventAggregator.GetEvent<ShellLayoutChangeEvent>().Publish("anindya");
    }

    private bool IsValid(string param)
    {
        if (param.Length > 0)

我的 DashboardViewModel.cs 代码如下:-

private bool _dashboardVisible;
    public bool DashboardVisible
    {
        get
        {
            return _dashboardVisible;
        }
        set
        {
            _dashboardVisible = value;
            OnPropertyChanged("DashboardVisible");
        }

    }
    private string myName;
    public string MyName
    {
        get
        {
            return myName;
        }
        set
        {
            myName = value;
            OnPropertyChanged("MyName");
        }
    }

    public DashboardViewModel()
    {
        MyName = "anindya";            
    }

现在的输出是: 1.Initially DashboardView 是不可见的。2. 登录成功后,尽管我设置了 DashborardVM.DashboardVisible = true,但 DashboardView 不可见;在我的 loginviewmode.cs 上。

我正在使用棱镜设计模式。以下方式我正在注册视图和视图模型。

public class ModuleDashboardModule: IModule
{
    IUnityContainer _container;
    IRegionManager _regionManager;

    public ModuleDashboardModule(IUnityContainer container,
                                IRegionManager regionManager)
    {
        _container = container;
        _regionManager = regionManager;

    }

    public void Initialize()
    {
        _container.RegisterType<ILoginView, LoginView>();
        _container.RegisterType<ILoginViewModel, LoginViewModel>();
        _container.RegisterType<IDashboardView, DashboardView>();
        _container.RegisterType<IDashboardViewModel, DashboardViewModel>();

        _regionManager.RegisterViewWithRegion(RegionNames.DashboardRegion,
                                                typeof(LoginView));
        _regionManager.RegisterViewWithRegion(RegionNames.DashboardRegion,
                                                typeof(DashboardView));
    }
}

这是我的 bootstrapper.cs 类:--

public class BootStrapper : UnityBootstrapper,IDisposable
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<Shell>();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();

        App.Current.MainWindow = (Window)Shell;
        App.Current.MainWindow.Show();
    }

    protected override void ConfigureModuleCatalog()
    {
        base.ConfigureModuleCatalog();

        Type moduleAType = typeof(ModuleDetailsModule);
        Type moduleNewForm = typeof(ModuleNewFormModule);
        Type moduleToolbarType = typeof(ModuleToolbarModule);
        Type moduleFooterType = typeof(ModuleFooterModule);
        Type moduleDashboardType = typeof(ModuleDashboardModule);
        Type moduleInvestmentType = typeof(ModuleInvestmentModule);
        Type moduleInvestmentDetailsType = typeof(ModuleInvestmentDetailsModule);

        ModuleCatalog.AddModule
        (
            new ModuleInfo()
            {
                ModuleName = moduleAType.Name,
                ModuleType = moduleAType.AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            }

        );
        ModuleCatalog.AddModule
        (
            new ModuleInfo()
            {
                ModuleName = moduleNewForm.Name,
                ModuleType = moduleNewForm.AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            }

        );

        ModuleCatalog.AddModule
        (
            new ModuleInfo()
            {
                ModuleName = moduleToolbarType.Name,
                ModuleType = moduleToolbarType.AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            }

        );

        ModuleCatalog.AddModule
        (
            new ModuleInfo()
            {
                ModuleName = moduleFooterType.Name,
                ModuleType = moduleFooterType.AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            }

        );

        ModuleCatalog.AddModule
        (
            new ModuleInfo()
            {
                ModuleName = moduleDashboardType.Name,
                ModuleType = moduleDashboardType.AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            }

        );

        ModuleCatalog.AddModule
            (
              new ModuleInfo()
              {
                  ModuleName = moduleInvestmentType.Name,
                  ModuleType = moduleInvestmentType.AssemblyQualifiedName,
                  InitializationMode = InitializationMode.WhenAvailable
              }
            );

        ModuleCatalog.AddModule
            (
            new ModuleInfo()
            {
                ModuleName = moduleInvestmentDetailsType.Name,
                ModuleType = moduleInvestmentDetailsType.AssemblyQualifiedName,
                InitializationMode = InitializationMode.WhenAvailable
            }
            );
    }

我的 LoginView.xaml.cs 文件是:

public partial class LoginView : UserControl,ILoginView
{
    [InjectionConstructor]
    public LoginView(LoginViewModel viewModel)
    {
        InitializeComponent();
        this.ViewModel = viewModel;
    }

    public IViewModel ViewModel
    {
        get
        {
            return (IViewModel)DataContext;
        }
        set
        {
            DataContext = value;
        }
    }
}

我的 DashboardView.xaml.cs 如下:

public partial class DashboardView : UserControl,IDashboardView
{
    DashboardViewModel viewModel = new DashboardViewModel();
    [InjectionConstructor]
    public DashboardView()
    {
        InitializeComponent();
        this.DataContext = viewModel;
        //this.ViewModel = viewModel;
    }

    public IViewModel ViewModel
    {
        get
        {
            return (IViewModel)DataContext;
        }
        set
        {
            DataContext = value;
        }
    }
}

我没有得到我犯错的地方。任何帮助都是可观的。

标签: wpfxamlmvvmprism

解决方案


这都是关于设置正确的数据上下文。

似乎您没有为仪表板视图设置数据上下文。因此 loginViewModel 成为仪表板视图的数据上下文。这是因为如果未显式设置,数据上下文将从 xaml 的父控件继承。

尝试为内容控制设置数据上下文

    <ContentControl DataContext="{Binding DashborardVM}">
    <ContentControl.Template>
        <ControlTemplate TargetType="{x:Type ContentControl}">
            <Grid>
                <Border >
                    <ContentPresenter/>
                </Border>
            </Grid>
        </ControlTemplate>
    </ContentControl.Template>
    <local:DashboardView  Visibility="{Binding DashboardVisible, Converter={StaticResource BoolVisibilityConverter}}"/>
</ContentControl> 

否则,您将不得不以格式进行所有绑定

{Binding DashborardVM.DashboardVisible}
{Binding DashborardVM.property}

编辑-顺便说一句,如果您使用的是棱镜,请检查视图模型是否已正确注册,以便它们自动分配。并且可能将可见性设置为

<local:DashboardView  Visibility="{Binding DashborardVM.DashboardVisible, Converter={StaticResource BoolVisibilityConverter}}"/>

会有所帮助,因为这里的数据上下文是 LoginViewmodel


推荐阅读