如何使用 Caliburn.Micro 和 Ninject 重用 MVVM 中的新视图

问题描述 投票:0回答:0

我正在测试动态修改网格控件结构的可能性(例如行数/列数)。

我正在使用最新版本的 Caliburn.Micro 和 Ninject 并使用 GridHelpers(我已经修改)来绑定行数和列数。

我的应用程序的完整代码可在Github

我创建了一个用户控件 MyGridView:

<UserControl x:Class="GridHelpersSample.MyGridView"
             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:gh="clr-namespace:GridHelpers;assembly=GridHelpers"
             xmlns:cal="http://www.caliburnproject.org"
             xmlns:local="clr-namespace:GridHelpersSample"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <ItemsControl ItemsSource="{Binding ButtonViewModels}">
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Grid.Row" Value="{Binding GridRow}" />
                    <Setter Property="Grid.Column" Value="{Binding GridColumn}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate >
                <DataTemplate >
                    <Button cal:Message.Attach="[Event Click] = [Action OnButtonClick($dataContext)]"
                                Content="{Binding Content}"/>
                </DataTemplate >
            </ItemsControl.ItemTemplate >
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid ShowGridLines="true" 
                        gh:GridHelpers.RowCount = "{Binding RowCount, Mode=TwoWay}"
                              gh:GridHelpers.ColumnCount = "{Binding ColumnCount, Mode=TwoWay}"
                              gh:GridHelpers.StarRows = "{Binding StarRows, Mode=TwoWay}"
                              gh:GridHelpers.StarColumns = "{Binding StarColumns, Mode=TwoWay}"
                              gh:GridHelpers.PixelRows = "{Binding PixelRows, Mode=TwoWay}"
                              gh:GridHelpers.PixelColumns = "{Binding PixelColumns, Mode=TwoWay}" >

                    </Grid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <!-- Now define a container that will host the ItemsControl -->
            <!--<ItemsControl.ItemsPanel >
                    <ItemsPanelTemplate >
                        <VirtualizingStackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate >
                </ItemsControl.ItemsPanel >-->
        </ItemsControl >
    </Grid>
</UserControl>

关联的视图模型:

using Caliburn.Micro;

namespace GridHelpersSample
{
    public class MyGridViewModel : Screen
    {
        public BindableCollection<ButtonViewModel> ButtonViewModels { get; set; }

        public MyGridViewModel(Main2ViewModel main2ViewModel)
        {
            RowCount = main2ViewModel.RowCount;
            ColumnCount = main2ViewModel.ColumnCount;
            StarRows = main2ViewModel.StarRows;
            StarColumns = main2ViewModel.StarColumns;
            PixelRows = main2ViewModel.PixelRows;
            PixelColumns = main2ViewModel.PixelColumns;
            ButtonViewModels = main2ViewModel.ButtonViewModels;
        }

        #region datas for defining grid
        private string rowCount;
        public string RowCount
        {
            get { return rowCount; }
            set
            {
                rowCount = value;
                NotifyOfPropertyChange(() => RowCount);
            }
        }
        private string columnCount;
        public string ColumnCount
        {
            get { return columnCount; }
            set
            {
                columnCount = value;
                NotifyOfPropertyChange(() => ColumnCount);
            }
        }
        private string starRows;
        public string StarRows
        {
            get { return starRows; }
            set
            {
                starRows = value;
                NotifyOfPropertyChange(() => StarRows);
            }
        }
        private string starColumns;
        public string StarColumns
        {
            get { return starColumns; }
            set
            {
                starColumns = value;
                NotifyOfPropertyChange(() => StarColumns);
            }
        }

        private string pixelRows;
        public string PixelRows
        {
            get { return pixelRows; }
            set
            {
                pixelRows = value;
                NotifyOfPropertyChange(() => PixelRows);
            }
        }
        private string pixelColumns;

        public string PixelColumns
        {
            get { return pixelColumns; }
            set
            {
                pixelColumns = value;
                NotifyOfPropertyChange(() => PixelColumns);
            }
        }
        #endregion

        public void OnButtonClick(ButtonViewModel context)
        {

        }
    }
}

Main2View 有一个内容控件和所有设置来定义用户控件中定义的网格结构。

<Window x:Class="GridHelpersSample.Main2View"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:gh="clr-namespace:GridHelpers;assembly=GridHelpers"
        xmlns:cal="http://www.caliburnproject.org"       
        xmlns:local="clr-namespace:GridHelpersSample"
        mc:Ignorable="d"
        Title="Main2View" Height="600" Width="1000">
    <Window.Resources>
        <Style x:Key="LabelStyle" TargetType="Label">
            <Setter Property="Width" Value="120" />
            <Setter Property="Margin" Value="5" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Foreground" Value="Blue" />
        </Style>
        <Style x:Key="TextBoxStyle" TargetType="TextBox">
            <Setter Property="Width" Value="120" />
            <Setter Property="Margin" Value="5" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="FontWeight" Value="Regular" />
            <Setter Property="Foreground" Value="Black" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <!--<Setter Property="cal:Message.Attach" Value="[Event LostFocus] = [Action TextBox_LostFocus($source, $this)]" />-->
            <Style.Triggers>
                <Trigger Property="Name" Value="RowCount">
                    <Setter Property="Width" Value="30"/>
                </Trigger>
                <Trigger Property="Name" Value="ColumnCount">
                    <Setter Property="Width" Value="30"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid x:Name="MainGrid"
        gh:GridHelpers.RowCount="2"
        gh:GridHelpers.ColumnCount="1"
        gh:GridHelpers.StarRows="1"
        gh:GridHelpers.StarColumns="*">
        <StackPanel Orientation="Vertical" Grid.Row="0" >
            <Separator />
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Label Content="RowCount:" Style="{StaticResource LabelStyle}" />
                <TextBox x:Name="RowCount" Style="{StaticResource TextBoxStyle}" />
                <Label Content="StarRows:" Style="{StaticResource LabelStyle}" />
                <TextBox x:Name="StarRows" Style="{StaticResource TextBoxStyle}" />
                <Label Content="PixelRows:" Style="{StaticResource LabelStyle}" />
                <TextBox x:Name="PixelRows" Style="{StaticResource TextBoxStyle}" />
                <Button x:Name="Valider" Content="Valider la saisie" Width="100" 
                        Margin="30,20,0,-20" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Label Content="ColumnCount:" Style="{StaticResource LabelStyle}" />
                <TextBox x:Name="ColumnCount" Style="{StaticResource TextBoxStyle}" />
                <Label Content="StarColumns:" Style="{StaticResource LabelStyle}" />
                <TextBox x:Name="StarColumns" Style="{StaticResource TextBoxStyle}" />
                <Label Content="PixelColumns:" Style="{StaticResource LabelStyle}" />
                <TextBox x:Name="PixelColumns" Style="{StaticResource TextBoxStyle}" />
                <Button Width="100" Visibility="Hidden" Height="0" Margin="30,0,0,0"/>
            </StackPanel>
            <Separator />
        </StackPanel>
        <ContentControl x:Name="myGridViewModel" Grid.Row="1"/>
    </Grid>
</Window>

Main2ViewModel的代码:

using Caliburn.Micro;
using Ninject;
using Ninject.Syntax;
using System.Collections.Generic;

namespace GridHelpersSample
{
    public class Main2ViewModel : Screen
    {
        private readonly IResolutionRoot _resolutionRoot;
        private readonly IKernel _kernel;
        public BindableCollection<ButtonViewModel> ButtonViewModels { get; set; }
        public MyGridViewModel myGridViewModel { get; set; }
        public Main2ViewModel(IResolutionRoot resolutionRoot, IKernel kernel) 
        {
            _resolutionRoot = resolutionRoot;
            _kernel = kernel;
            RowCount = "3";
            ColumnCount = "3";
            StarRows = "*";
            StarColumns = "*";
            PixelRows = "";
            PixelColumns = "";

            AddNewContent();
        }

        #region datas for defining grid
        private string rowCount;
        public string RowCount
        {
            get { return rowCount; }
            set
            {
                rowCount = value;
                NotifyOfPropertyChange(() => RowCount);
            }
        }
        private string columnCount;
        public string ColumnCount
        {
            get { return columnCount; }
            set
            {
                columnCount = value;
                NotifyOfPropertyChange(() => ColumnCount);
            }
        }
        private string starRows;
        public string StarRows
        {
            get { return starRows; }
            set
            {
                starRows = value;
                NotifyOfPropertyChange(() => StarRows);
            }
        }
        private string starColumns;
        public string StarColumns
        {
            get { return starColumns; }
            set
            {
                starColumns = value;
                NotifyOfPropertyChange(() => StarColumns);
            }
        }

        private string pixelRows;
        public string PixelRows
        {
            get { return pixelRows; }
            set
            {
                pixelRows = value;
                NotifyOfPropertyChange(() => PixelRows);
            }
        }
        private string pixelColumns;

        public string PixelColumns
        {
            get { return pixelColumns; }
            set
            {
                pixelColumns = value;
                NotifyOfPropertyChange(() => PixelColumns);
            }
        }
        #endregion

        public void Valider()
        {            
            AddNewContent();
        }
        public List<ButtonViewModel> CreateButton()
        {
            var myView = _resolutionRoot.Get<Main2View>();
            var t = myView.MainGrid;
            var list = new List<ButtonViewModel>();
            for (int i = 0; i < int.Parse(RowCount); i++)
            {
                for (int j = 0; j < int.Parse(ColumnCount); j++)
                {
                    var button = new ButtonViewModel
                    {
                        Content = $"R{i} C{j}",
                        GridRow = i,
                        GridColumn = j
                    };

                    list.Add(button);
                }
            }
            return list;
        }

        private void AddNewContent()
        {
            ButtonViewModels = new BindableCollection<ButtonViewModel>(CreateButton());
            myGridViewModel = new MyGridViewModel(this);
        }
    }
}

在视图/视图模型的初始化过程中一切都很好,但是当我更改 RowCount 或 RowColumn 的值并单击按钮时,问题就开始了。

我正在等待新视图的初始化,但事实并非如此,视图 MyGridView 没有重新加载..

这是助推器:

using Caliburn.Micro;
using Ninject;
using System;
using System.Collections.Generic;
using System.Windows;

namespace GridHelpersSample
{
    public class Bootstrapper : BootstrapperBase
    {
        private IKernel kernel;
        public Bootstrapper()
        {
            Initialize();
        }

        protected override void Configure()
        {
            kernel = new StandardKernel();
            kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
            kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();
            kernel.Bind<MyGridViewModel>().ToSelf().InTransientScope();
            //kernel.Bind<MyGridViewModel>().ToSelf().InSingletonScope();
            var bindings0 = kernel.GetBindings(typeof(MyGridViewModel));
            //var bindings1 = kernel.GetBindings(typeof(MainViewModel));
        }
        protected override async void OnStartup(object sender, StartupEventArgs e)
        {
            await DisplayRootViewForAsync<Main2ViewModel>();
        }
        protected override object GetInstance(Type service, string key)
        {
            return kernel.Get(service);
        }
        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return kernel.GetAll(service);
        }
        protected override void BuildUp(object instance)
        {
            kernel.Inject(instance);
        }
    }
}

即使我使用 InTransientScope() 我也没有到达重新启动新视图 这表明要使用新的视图实例..但也许我遗漏了一些东西..

无论如何,应用程序似乎有问题,因为当我关闭主视图时,调试器没有完成,我必须使用 VS2022 中的红色按钮停止应用程序

c# wpf grid ninject caliburn.micro
© www.soinside.com 2019 - 2024. All rights reserved.