如何并排绑定两个视图

Posted

技术标签:

【中文标题】如何并排绑定两个视图【英文标题】:How to bind two Views side by side 【发布时间】:2017-12-21 00:59:34 【问题描述】:

我一直在关注这个Walkthrough,它很好地解释了两个视图之间的切换以及更多内容。

我正在尝试调整项目,而不是在两个视图之间切换,而是并排显示两个视图。

Andy 在他的 MainWindowViewModel 中设置以下内容,将 ViewModel 放入 OC:

public class MainWindowViewModel : NotifyUIBase

    public ObservableCollection<ViewVM> Views get;set;

    public MainWindowViewModel()
    
        ObservableCollection<ViewVM> views = new ObservableCollection<ViewVM>
        
            new ViewVM ViewDisplay="Customers", ViewType = typeof(CustomersView), ViewModelType = typeof(CustomersViewModel),
            new ViewVM ViewDisplay="Products", ViewType = typeof(ProductsView), ViewModelType = typeof(ProductsViewModel)
        ;
        Views = views;
        RaisePropertyChanged("Views");
        views[0].NavigateExecute();
    

在 MainWindow.xaml.cs 导航调用 ShowUserControl() 来设置视图

public partial class MainWindow : Window

    public MainWindow()
    
        InitializeComponent();

        // Apply default form level font style
        Style = (Style)FindResource(typeof(Window));
        Messenger.Default.Register<NavigateMessage>(this, (action) => ShowUserControl(action));
        this.DataContext = new MainWindowViewModel();
    

    private void ShowUserControl(NavigateMessage nm)
    
        EditFrame.Content = nm.View;
    

我的代码:

我不会在 OC 中使用它们,也不会在视图之间切换,它们会同时并排显示。所以我在想我需要做的是

public class MainWindowViewModel : NotifyUIBase

    private ViewVM m_MobileDeviceRequestsVM;
    private ViewVM m_AuthorizedMobileDevicesVM;

    public ViewVM MobileDeviceRequestsVM
    
        get  return m_MobileDeviceRequestsVM; 
    

    public ViewVM AuthorizedMobileDevicesVM
    
        get  return m_AuthorizedMobileDevicesVM; 
    

    public MainWindowViewModel()
    
        m_MobileDeviceRequestsVM = new ViewVM  ViewDisplay = "MobileDeviceRequests", ViewType = typeof(MobileDeviceRequestsView), ViewModelType = typeof(MobileDeviceRequestsViewModel) ;
        m_AuthorizedMobileDevicesVM = new ViewVM  ViewDisplay = "AuthorizedMobileDevices", ViewType = typeof(AuthorizedMobileDevicesView), ViewModelType = typeof(AuthorizedMobileDevicesViewModel) ;
    

我面临的问题是如何将这些 ViewModel 视图绑定到我的网格中,尝试使用几个 ContentControl 但这不起作用。 我怎样才能做到这一点?

<Window x:Class="MobileDeviceAuthenticator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MobileDeviceAuthenticator"
        Title="Device Authorization" Height="381" Width="879">
    <Grid>
        <Grid Margin="0,25,0,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Label Content="Authorized Devices" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" Margin="20,10,0,0" VerticalAlignment="Top" />
            <ContentControl Grid.Row="1" Grid.Column="0" Content="Binding AuthorizedMobileDevicesVM.View" />

            <Label Content="Device Requests" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Margin="20,10,0,0" VerticalAlignment="Top" />
            <ContentControl Grid.Row="1" Grid.Column="1" Content="Binding MobileDeviceRequestsVM.View" />
        </Grid>
    </Grid>
</Window>

【问题讨论】:

看起来您链接的示例使用 ViewVM 来促进使用“NavigateMessage”来控制要显示的视图。既然您没有切换视图,那么您仍然需要 ViewVM 有什么原因吗?尽管作者说这是一种 MVVM 方法,但使用 viewmodel 类存储用户控件并不是 MVVM。并不是说我无论如何都是 MVVM 纯粹主义者,我只是觉得使用这种机制会使解决问题的方法复杂化。此外,如果您的 AuthorizedMobileDevicesVM.View 确实是某种用户控件 - 它应该可以工作。您是否确认没有绑定错误? 可能有帮助:youtube.com/watch?v=xUwk2-_tRzo 【参考方案1】:

在对我对该方法的保留发表评论后,我再次查看了示例的 ViewVM 类。忽略这些并假设您没有修改下面示例的 ViewVM 代码:

 public class ViewVM
    
        public string ViewDisplay  get; set; 
        public Type ViewType  get; set; 
        public Type ViewModelType  get; set; 
        public UserControl View  get; set; 
        public RelayCommand Navigate  get; set; 
        public ViewVM()
        
            Navigate = new RelayCommand(NavigateExecute);
        
        public void NavigateExecute()
        
            if(View == null && ViewType != null)
            
                View = (UserControl)Activator.CreateInstance(ViewType);
            
            var msg = new NavigateMessage  View = View, ViewModelType = ViewModelType, ViewType = ViewType ;
            Messenger.Default.Send<NavigateMessage>(msg);
        
    

问题是 View 属性仅在调用 NavigateExecute 时通过反射分配给。当您绑定到AuthorizedMobileDevicesVM.View 时,它还没有被实例化。您可以将反射代码移动到您的案例的构造函数中,它会起作用。当然,这意味着如果您在其他地方使用 ViewVM 进行页面导航,它会增加应用程序的内存使用量 - 看起来它的设计旨在仅在必要时创建视图。

【讨论】:

这一切都说得通,感谢您注意到您的预订。我已经不再对这个特定窗口使用 ViewVM,因为我同意在这种情况下没有必要。您还给出了我还不知道的原因和解决方案。感谢您的时间!

以上是关于如何并排绑定两个视图的主要内容,如果未能解决你的问题,请参考以下文章

iOS Auto Layout - 如何让两个堆叠的纵向视图在横向中并排移动?

将两个 UIViewController 并排放在屏幕上

如何并排执行两个 QGraphicsViews 的 50/50 布局?

如何使用情节提要约束将两个 UIPickerView 并排均匀分布?

UICollectionViewCell sizeForRowAtIndexPath 和并排的两个视图

word中,怎样让两个表格并排放在一起一页纸