You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prism多视图绑定同一ViewModel构造函数触发两次及ListBox编辑问题咨询

问题1 构造函数触发两次的原因

Prism的RegisterForNavigation默认会将关联的ViewModel注册为瞬态服务,每次首次解析对应视图时都会创建新的ViewModel实例:

  1. 应用初始化时导航到GCodeEditorView,首次解析创建第一个GCodeEditorViewModel实例
  2. 第一次切换到GCodeProductionView时,因为该视图也绑定了GCodeEditorViewModel,首次解析时又创建了第二个实例
  3. 后续切换不会触发构造是因为Prism区域默认开启了视图缓存(KeepAlive默认值为true),已经加载过的视图和关联的ViewModel会被直接复用,不会重新创建。

如果要实现两个视图共用同一个ViewModel实例,只需要在注册类型时手动将GCodeEditorViewModel注册为单例即可,修改RegisterTypes方法:

public void RegisterTypes(IContainerRegistry containerRegistry)
{
    // 手动把ViewModel注册为单例
    containerRegistry.RegisterSingleton<GCodeEditorViewModel>();
    containerRegistry.RegisterForNavigation<MenuView, MenuViewModel>();
    containerRegistry.RegisterForNavigation<GCodeEditorView, GCodeEditorViewModel>();
    containerRegistry.RegisterForNavigation<GCodeProductionView, GCodeEditorViewModel>();
}

问题2 ListBox编辑项按回车新增行实现

你需要将GCode行数据绑定到ObservableCollection<T>类型的集合,同时绑定ListBox的选中项到ViewModel属性,通过监听编辑框的回车键事件触发新增逻辑即可,符合MVVM规范的实现方式如下:

  1. XAML部分配置ItemTemplate,用交互触发器将编辑框的键盘事件绑定到ViewModel命令:
<ListBox ItemsSource="{Binding GCodeLines}" SelectedItem="{Binding SelectedGCodeLine}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <!-- 这里假设你用自定义GCode行实体类,Text绑定行内容属性 -->
            <TextBox Text="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="KeyDown">
                        <prism:InvokeCommandAction 
                            Command="{Binding DataContext.AddNewLineCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                            CommandParameter="{Binding}"
                            PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
  1. ViewModel新增命令逻辑:
// GCode行集合
public ObservableCollection<GCodeLineModel> GCodeLines { get; set; }
// 当前选中行
public GCodeLineModel SelectedGCodeLine { get; set; }

private void ExecuteAddNewLineCommand(object parameter)
{
    var args = (KeyEventArgs)parameter;
    // 只响应回车键
    if (args.Key != Key.Enter) return;
    
    var currentLine = (GCodeLineModel)((InvokeCommandAction)args.Source).CommandParameter;
    int currentIndex = GCodeLines.IndexOf(currentLine);
    // 在当前行下方插入空行
    GCodeLines.Insert(currentIndex + 1, new GCodeLineModel() { Content = string.Empty });
    // 自动选中新行直接进入编辑状态
    SelectedGCodeLine = GCodeLines[currentIndex + 1];
    RaisePropertyChanged(nameof(SelectedGCodeLine));
}

内容的提问来源于stack exchange,提问作者Buruhazard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 06:51:04