DevExpress DashBoard 添加自定义组件(Web浏览器)
自定义Dashbarod组件
最近由于项目需要,需要在原有DevExpress DashBoard配置的基础上提高可配置元素,研究一下DashBoard源码,总结出了一个可以实践的方法。
自定义Winform 设计器组件
首先我们需要顶一个组件模型和组件的数据模型:WebDashBoardItem和WebDashBoardViewModel。这两个类我们在设计器以及viewer中都会用到,用来识别组件类型以及传递数据。
然后我们组件的可视化控件WebDashBoardItemViewer,这个用于设计器以及WinForm的viewer中。下面我们从操作流程来说:
- InsertWebCommand ,创建自定义组件,通过创建该命令来执行创建组件操作;
- EditUrlCommand ,编辑自定义组件,通过创建该命令来执行组件数据或配置的编辑操作;
- 我们需要在设计器界面人为添加两个菜单按钮,用于执行创建和编辑操作。
- 自定义新的设计器用于承载自定义的命令以及组件MyDashBoardDesigner;
新增命令InsertWebCommand
public class InsertWebCommand: InsertItemCommand<WebDashBoardItem>
{
public InsertWebCommand(DashboardDesigner control) : base(control) { }
public override DashboardCommandId Id
{
get
{
return new DashboardCommandId(19909);
}
}
public override DashboardWinStringId MenuCaptionStringId
{
get
{
return DashboardWinStringId.AddDashboardParameter;
}
}
public override DashboardWinStringId DescriptionStringId
{
get
{
return DashboardWinStringId.AddDashboardParameter;
}
}
protected override DashboardStringId DefaultNameId
{
get
{
return DashboardStringId.CustomItems;
}
}
}
}
编辑命令EditUrlCommand
public class EditUrlCommand: DashboardItemCommand<WebDashBoardItem>
{
public override DashboardCommandId Id { get { return new DashboardCommandId(9999); } }
public override DashboardWinStringId MenuCaptionStringId { get { return DashboardWinStringId.CommandImageLoadCaption; } }
public override DashboardWinStringId DescriptionStringId { get { return DashboardWinStringId.CommandImageLoadDescription; } }
public override string ImageName { get { return "ImageLoad"; } }
public EditUrlCommand(DashboardDesigner control) : base(control)
{
}
protected override void ExecuteInternal(ICommandUIState state)
{
using (UrlEditor dialog = new UrlEditor(base.DashboardItem))
{
if(dialog.ShowDialog() == DialogResult.OK)
{
WebUrlHistoryItem historyItem = GetHistoryItem(DashboardItem, dialog.Url);
if (historyItem != null)
{
historyItem.Redo(Control);
}
}
}
}
private WebUrlHistoryItem GetHistoryItem(WebDashBoardItem dashBoardItem,string url)
{
WebUrlHistoryItem urlHistoryItem = new WebUrlHistoryItem(dashBoardItem, url);
return urlHistoryItem;
}
}
public class WebUrlHistoryItem : DashboardItemHistoryItem<WebDashBoardItem>
{
private WebDashBoardItem prev;
private string next;
protected override DashboardWinStringId CaptionId { get { return DashboardWinStringId.HistoryItemImageOpen; } }
public WebUrlHistoryItem(WebDashBoardItem dashboardItem, string uri) : base(dashboardItem)
{
prev = dashboardItem;
next = uri;
}
protected override void PerformUndo()
{
(base.DashboardItem as WebDashBoardItem).Url = prev.Url;
}
protected override void PerformRedo()
{
(base.DashboardItem as WebDashBoardItem).Url = next;
}
}
自定义设计器MyDashBoardDesigner
public class MyDashBoardDesigner : DashboardDesigner
{
public MyDashBoardDesigner() : base()
{
base.AddCommand(new DashboardCommandId(9999), typeof(EditUrlCommand));
base.AddCommand(new DashboardCommandId(10000), typeof(InsertWebCommand));
}
}
下面就是组件相关控件以及模型
可视化控件 WebDashBoardItemViewer
[DXToolboxItem(false)]
public class WebDashBoardItemViewer : DashboardItemViewer
{
readonly WebBrowser web = new WebBrowser();
protected override Control GetUnderlyingControl()
{
return web;
}
protected override void PrepareViewControl()
{
}
protected override void UpdateViewer()
{
base.UpdateViewer();
WebDashBoardViewModel vm = ViewModel as WebDashBoardViewModel;
web.Navigate(vm.url);
}
public WebDashBoardItemViewer() : base()
{
}
private void OnControlMouseWheel(object sender, MouseEventArgs e)
{
RaiseMouseWheel();
}
private void OnControlMouseHover(object sender, EventArgs e)
{
RaiseMouseHover();
}
private void OnControlMouseUp(object sender, MouseEventArgs e)
{
RaiseMouseUp(e.Location);
}
private void OnControlMouseDown(object sender, MouseEventArgs e)
{
RaiseMouseDown(e.Location);
}
private void OnControlMouseLeave(object sender, EventArgs e)
{
RaiseMouseLeave();
}
private void OnControlMouseEnter(object sender, EventArgs e)
{
RaiseMouseEnter();
}
private void OnControlMouseMove(object sender, MouseEventArgs e)
{
RaiseMouseMove(e.Location);
}
private void OnControlMouseDoubleClick(object sender, MouseEventArgs e)
{
RaiseDoubleClick(e.Location);
}
private void OnControlMouseClick(object sender, MouseEventArgs e)
{
RaiseClick(e.Location);
}
protected override Control CreateViewControl()
{
return web;
}
protected override void PrepareClientState(ItemViewerClientState state)
{
state.ViewerArea = GetControlClientArea(web);
}
}
组件模型 WebDashBoardItem
[DashboardItemType("Web")]
public class WebDashBoardItem : DashboardItem
{
public string url = "https://www.baidu.com/";
protected override string CaptionPrefix
{
get
{
return "Web";
}
}
protected override DashboardItemViewModel CreateViewModel()
{
return new WebDashBoardViewModel(this);
}
[DefaultValue("https://www.baidu.com/")]
public string Url
{
get { return url; }
set
{
if (url != value)
{
url = value;
base.OnChanged(ChangeReason.View, this, null);
}
}
}
protected override void SaveToXml(XElement element)
{
base.SaveToXml(element);
element.Add(new XAttribute("url", url));
}
protected override XElement SaveToXml()
{
return base.SaveToXml();
}
protected override void LoadFromXmlInternal(XElement element)
{
base.LoadFromXmlInternal(element);
this.Url = element.GetAttributeValue("url");
}
}
组件数据模型 WebDashBoardViewModel
public class WebDashBoardViewModel : DashboardItemViewModel
{
public string url { get; set; }
public WebDashBoardViewModel() : base()
{ }
public WebDashBoardViewModel(WebDashBoardItem item) : base(item)
{
url = item.Url;
}
}
自定义WPF显示组件
首先我们先顶一个组件样式模板 WebItemThemeKeyExtension,用于识别可视化组件的控件模板以及样式。
然后我们需要基于WPF渲染加载组件模板机制,重新自定义一套新的渲染模板。
WPF 自定义设计器及相关类
[DXToolboxBrowsable]
public class MyDashBoardControl : DashboardControl
{
protected override BaseDashboardViewModelXpf CreateDashboardViewModel(Dashboard dashboard)
{
return ViewModelSource.Create(() => new MyDashboardViewModelXpf(new XPFService(this, this, Dashboard)) { AllowPrintDashboardItems = AllowPrintDashboardItems });
}
}
public class MyDashboardViewModelXpf: BaseDashboardViewModelXpf
{
public MyDashboardViewModelXpf(XPFService dataService) : base(dataService)
{
}
protected override IDashboardItemViewModelXpf CreateViewModel(string itemName)
{
BaseDashboardItemViewModelXpf viewModelXpf;
XpfItemModel itemModel = XpfDataService.GetItemModel(itemName);
switch (itemModel.ItemType)
{
case "Web":
viewModelXpf = ViewModelSource.Create(() => new WebItemViewModelXpf(this, itemName));
break;
default:
viewModelXpf = new CustomItemViewModelXpf(this, itemName);
break;
}
return viewModelXpf;
}
}
……
public class WebItemViewModelXpf : BaseDashboardItemViewModelXpf
{
public WebItemViewModelXpf(object parent, string itemName)
: base(parent, itemName)
{
}
WebDashBoardViewModel ViewModel { get { return (WebDashBoardViewModel)ItemViewModel; } }
public override DevExpress.DashboardXpf.DashboardItemType ItemType
{
get
{
return DevExpress.DashboardXpf.DashboardItemType.Custom;
}
}
public string Url
{
get
{
return ViewModel.url;
}
}
public override DevExpress.DashboardXpf.DashboardLayoutItem CreateLayoutItem()
{
return new WebDashboardLayoutItem();
}
}
WPF 样式文件
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxdash="http://schemas.devexpress.com/winfx/2008/xaml/dashboard"
xmlns:dxdashi="clr-namespace:DevExpress.DashboardXpf.Internal;assembly=DevExpress.Xpf.Dashboard.v17.2" xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm">
<Style x:Key="webBrowserStyle" TargetType="{x:Type chrome:ChromiumWebBrowser}">
<Setter Property="Address" Value="{Binding Url}" />
</Style>
<DataTemplate x:Key="webBrowserTemplate">
<chrome:ChromiumWebBrowser Style="{Binding Path=(dxdash:DashboardLayoutItem.ViewStyle), RelativeSource={RelativeSource TemplatedParent}}"/>
</DataTemplate>
<Style x:Key="sddd" TargetType="{x:Type mydash:WebDashboardLayoutItem}" BasedOn="{StaticResource ResourceKey={x:Type dxdash:DashboardLayoutItem}}">
<Setter Property="ContentTemplate" Value="{StaticResource webBrowserTemplate}"/>
<Setter Property="ViewStyle" Value="{StaticResource webBrowserStyle}"/>
</Style>
……
</ResourceDictionary>
以上参考DevExpress 17.2源码完成