解决wpf,caliburn.micro框架,重复切换至某个ContentControl后,该界面所有绑定事件突然无效问题

很奇怪的问题,原因不明,多见于 <ContentControl Grid.Row="3" Grid.Column="2" cal:View.Model="{Binding Content}"/> 此种绑定场景下,对Content进行不同viewmodel的赋值,来达到切换界面内容的目的

解决办法:

换个思路,创建ItemsControl,包含所有要使用的子控件,使其中需要显示(激活)的子控件显示,其他则隐藏

View:

复制代码
<ItemsControl Grid.Row="3" Grid.Column="2" ItemsSource="{Binding Items}" Focusable="False" Height="{Binding ElementName=MainParent,Path=ActualHeight}" Width="{Binding ElementName=MainParent,Path=ActualWidth}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VirtualizingStackPanel.VirtualizationMode="Recycling" IsVirtualizing="True" VirtualizingPanel.ScrollUnit ="Pixel"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentControl cal:View.Model="{Binding IsAsync=True}">
                <ContentControl.Visibility>
                    <MultiBinding Converter="{StaticResource MultiCompareToVisibilityConverter}">
                        <Binding />
                        <Binding Path="DataContext.ActiveItem" RelativeSource="{RelativeSource AncestorType={x:Type ItemsControl}}"/>
                    </MultiBinding>
                </ContentControl.Visibility>
            </ContentControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
复制代码

ViewModel:

基类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class ActiveViewModel : BaseViewModel
{
    /// <summary>
    /// 设置显示页面
    /// </summary>
    /// <param name="screen"></param>
    /// <returns></returns>
    public Task SetActiveItem(Caliburn.Micro.Screen screen = null)
    {
        if (this.ActiveItem == screen)
            return Task.Run(() => this.Get<MainViewModel>().IsBusy = false);
        else
            return Task.Run(async () => await this.ActivateItemAsync(screen)).ContinueWith(__ =>
                 this.Get<MainViewModel>().IsBusy = false);
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
public class BaseViewModel : Conductor<object>.Collection.OneActive
{
    #region private fields
    /// <summary>
    /// 窗体管理器
    /// </summary>
    protected readonly IWindowManager windowManager;
    #endregion
 
    #region consturtor
    static BaseViewModel()
    {
        // Caliburn.Micro(CM) 穿过 Popup 绑定方法 http://www.cnblogs.com/gaoshang212/p/4203929.html
        ActionMessage.SetMethodBinding = context =>
        {
            var source = context.Source;
            System.Windows.DependencyObject currentElement = source;
            while (currentElement != null)
            {
                if (Caliburn.Micro.Action.HasTargetSet(currentElement))
                {
                    var target = Message.GetHandler(currentElement);
                    if (target != null)
                    {
                        var method = ActionMessage.GetTargetMethod(context.Message, target);
                        if (method != null)
                        {
                            context.Method = method;
                            context.Target = target;
                            context.View = currentElement;
                            return;
                        }
                    }
                    else
                    {
                        context.View = currentElement;
                        return;
                    }
                }
 
                //修改部分 Begin
                var pElement = System.Windows.Media.VisualTreeHelper.GetParent(currentElement);
                if (pElement == null
                    && currentElement.GetType().Name.Equals("PopupRoot", System.StringComparison.OrdinalIgnoreCase))
                {
                    if (currentElement is System.Windows.FrameworkElement ef)
                        pElement = ef.Parent;
                }
 
                currentElement = pElement;
                //End
            }
 
            if (source != null && source.DataContext != null)
            {
                var target = source.DataContext;
                var method = ActionMessage.GetTargetMethod(context.Message, target);
 
                if (method != null)
                {
                    context.Target = target;
                    context.Method = method;
                    context.View = source;
                }
                else
                {
                    source.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        };
    }
    /// <summary>
    /// 构造函数
    /// </summary>
    public BaseViewModel() => this.windowManager = this.Get<IWindowManager>();
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="windowManager"></param>
    public BaseViewModel(IWindowManager windowManager)
    {
        this.windowManager = windowManager;
    }
    #endregion
 
    #region public methods
    /// <summary>
    /// 根据类型和名称获取实例对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    public virtual T Get<T>(string name = null) => (T)IoC.Get<T>(name);
 
    /// <summary>
    /// 提示消息
    /// </summary>
    /// <param name="message">提示内容</param>
    /// <param name="isAsk">是否询问消息</param>
    /// <returns></returns>
    public bool? ShowMessage(string message, MessageType type = MessageType.正常)
        => MessageBoxExt.ShowMessage(message, type);
 
    /// <summary>
    ///
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    public void ShowWindow(BaseViewModel viewModel, bool dialog = true)
    {
        if (windowManager==null||viewModel==null) return;
        if (dialog)
            windowManager.ShowDialogAsync(viewModel);
        else
            windowManager.ShowWindowAsync(viewModel);
    }
    #endregion
}

  切换子控件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
……   
case ProcessStage.Camera:
        if (cameraViewModel==null)
            cameraViewModel=this.Get<CameraViewModel>();
        this.SetActiveItem(cameraViewModel);
        cameraViewModel.StartCamera();
        break;
    case ProcessStage.Photo:
        if (photoViewModel==null)
            photoViewModel=this.Get<PhotoViewModel>();
        this.SetActiveItem(photoViewModel);
        cameraViewModel.StopCamera();
        break;
……

  

posted @   dyfisgod  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示