解决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:
基类:
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);
}
}
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
}
切换子控件:
……
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;
……

浙公网安备 33010602011771号