如何将 Ninject 用于 MVVM 和 WPF

How to Use Ninject with MVVM and WPF

我正在努力使用 WPF 和 MVVM 模式构建应用程序。 在此应用程序中,我在 MainView 中有三个按钮 - 相机、锅炉、温度传感器。当我按下某个按钮时,它会在 window 的第二部分打开附加控件,其中包含有关所选小工具的信息。 我已经做到了,但是架构不好,因为主窗体“知道”某些对象。我的 MainView (XAML) 中有这段代码,它看起来不应该是这样的。

<Window ...>
    <Grid>
        <Grid.ColumnDefinitions>
        </Grid.ColumnDefinitions>
        <StackPanel>
            <Button Content="Камера"
                    Command="{Binding NavigationCameraCommand}"
                    Margin="5"
                    Height="30"/>
            <Button Content="Котёл"
                    Command="{Binding NavigateBoilerCommand}"
                    Margin="5"
                     Height="30"/>
            <Button Content="Датчик температуры"
                     Command="{Binding NavigationTemperatureSensorCommand}"
                    Margin="5"
                    Height="30"/>
        </StackPanel>

        <ContentControl Grid.Column="1"  Content="{Binding CurrentViewModel}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type viewmodels:CameraViewModel}">
                    <views:CameraView/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type viewmodels:BoilerViewModel}">
                    <views:BoilerVIew/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type viewmodels:TemperatureSensorViewModel}">
                    <views:TemperatureSensorView/>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
    </Grid>
</Window>

我需要用Ninject来处理这个问题。据我了解,我需要在定位器中定义成对的视图和模型,然后在注入视图时,将自动确定链接模型,创建它的实例并将其分配给视图上下文。

我还没有找到如何实现的示例。

谁能举例说明如何做到这一点或举例说明(最好有几个观点)?

我在 YouTube 上找到了这个视频,但仍然不明白它在多次观看时效果如何。 https://www.youtube.com/watch?v=yN4SgWHwhgk

看来你想得到另一个结果。 如果您计划在将来添加设备(动态生成按钮并使用自定义视图),您需要为每个设备(传感器、锅炉等)定义基本接口和实现,这应该作为不同的模块(库)。模块应该提供一些元数据、自定义视图和你想要的其他东西。 当您启动您的应用程序时,容器会加载具有已实现的基本接口的程序集,因此您可以获得设备并可以使用元数据动态生成按钮。然后,在必要时,您可以使用提供的视图或其他提供的属性或方法。

interface IDevice
{
    IDeviceMetadata Metadata { get; }
    UserControl View { get; }
}

interface IDeviceMetadata
{
    Guid Key { get; }
    string Name { get; }
    string Description { get; }
    string Version { get; }
}

class App
{
    public ICollection<IDevice> Devices { get; private set; }

    void LoadDevices()
    {
        Devices = Container.LoadFromDirectory("path_to_device_libraries(dlls)");
    }
}

class DevicesViewModel
{
    public IEnumerable<IDevice> Devices => App.Instance.Devices;

    public UserControl DeviceView { get { ... } set { ... } } // have to invoke PropertyChanged

    public ICommand ShowDeviceViewCommand => Command.Create<IDevice>(ShowDeviceView);
    
    private void ShowDeviceView(IDevice device)
    {
        DeviceView = device.View;
    }
}
<Window>
    <Grid>
        <ItemsControl ItemsSource="{Binding Devices}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding Path=Metadata.Name}"
                            Command="{Binding Path=DataContext.ShowDeviceViewCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                            Margin="5" Height="30"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <ContentControl Grid.Column="1"  Content="{Binding DeviceView}"/>
    </Grid>
</Window>