网上已经有人写过一些视图联动的帖子了,我这里将这个功能封装成一个类,以方便使用。
核心思想
第一步:组织需要关联的视图集合。这些视图要存在对应的UIView才有意义;
第二步:绑定UIApplication的Idling和ViewActivated事件;
1、Idling事件处理UI视图显示范围同步,以ActiveView为基准,调整其他视图;
2、ViewActivated事件监控是否要结束掉联动行为。
第三步: 触发自动撤销联动行为;
1、 当前激活操作视图不是传入视图集合中的一个,或者关联视图对应的UIView数量为0时,自动关闭关联;
2、其他异常情况时同样关闭事件关联。
源码
/// <summary>
/// 视图联动集合
/// </summary>
public class LinkViews
{
/*
* 关联关系自动关闭场景:
* 当前激活操作视图不是传入视图集合中的一个,或者关联视图对应的UIView数量为0时,自动关闭关联;
* 其他异常情况方式时同样关闭事件关联
*/
public LinkViews(IEnumerable<View> views)
{
Views = new ReadOnlyCollection<View>(new List<View>(views));
}
/// <summary>
/// 开启联动
/// </summary>
/// <param name="uiApplication"></param>
public void Start(UIApplication uiApplication)
{
uiApplication.Idling += OnIdling;
uiApplication.ViewActivated += OnViewActivated;
}
/// <summary>
/// 结束联动
/// </summary>
/// <param name="uiApplication"></param>
public void Stop(UIApplication uiApplication)
{
uiApplication.Idling -= OnIdling;
uiApplication.ViewActivated -= OnViewActivated;
}
/// <summary>
///关联视图信息
/// </summary>
public ReadOnlyCollection<View> Views { get; private set; }
private void OnViewActivated(object sender, ViewActivatedEventArgs e)
{
var uiApp = sender as UIApplication;
try
{
var uidoc = uiApp.ActiveUIDocument;
var doc = uidoc.Document;
var acview = doc.ActiveView;
if (!Views.Any(v => v.Id == acview.Id))
{
Stop(uiApp);
}
}
catch (Exception)
{
Stop(uiApp);
}
}
private void OnIdling(object sender, IdlingEventArgs e)
{
var uiApp = sender as UIApplication;
try
{
var uidoc = uiApp.ActiveUIDocument;
var acview = uidoc.Document.ActiveView;
var uiViews = uidoc.GetOpenUIViews();
var baseView = uiViews.FirstOrDefault(uView => uView.ViewId == acview.Id);
if (baseView == null)
{
Stop(uiApp);
return;
}
var viewCorners = baseView.GetZoomCorners();
bool hasLinkView = false;
foreach (View view in Views)
{
if (view.Id == baseView.ViewId)
continue;
var uiView = uiViews.FirstOrDefault(uView => uView.ViewId == view.Id);
uiView?.ZoomAndCenterRectangle(viewCorners[0], viewCorners[1]);
hasLinkView = true;
}
if (!hasLinkView)
{
Stop(uiApp);
}
}
catch (Exception)
{
Stop(uiApp);
}
}
}
使用方法
下面的命令使用了我架构中的基类,测试的话直接Copy使用Excute方法里的代码就可以了
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
[Button(ButtonName = "视图联动", TabName = "Test", PanelName = "Test")]
public class LinkViewCommand : ExternalCommand
{
private LinkViews m_LinkViews;
public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
if(m_LinkViews!=null)
{
m_LinkViews.Stop(commandData.Application);
}
var views=commandData.Application.ActiveUIDocument.Document.GetElements<View>();
m_LinkViews = new LinkViews(views);
m_LinkViews.Start(commandData.Application);
return Result.Succeeded;
}
}
效果
点击激活视图,则该视图成为基准视图