Wpf 如何在ESRI中绑定LineSymbol上的关联菜单?
我已为线条符号创建了一个ControlTemplate:Wpf 如何在ESRI中绑定LineSymbol上的关联菜单?,wpf,binding,contextmenu,symbols,Wpf,Binding,Contextmenu,Symbols,我已为线条符号创建了一个ControlTemplate: <esri:SimpleLineSymbol x:Key="PolylineSymbol" Width="3" > <esri:SimpleLineSymbol.ControlTemplate> <ControlTemplate> <Grid
<esri:SimpleLineSymbol
x:Key="PolylineSymbol"
Width="3"
>
<esri:SimpleLineSymbol.ControlTemplate>
<ControlTemplate>
<Grid
>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
...
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
...
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path
x:Name="Element" Fill="{x:Null}"
Stroke="Navy" StrokeThickness="3"
StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.ContextMenu>
<ContextMenu
x:Name="popUpMenu"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type esri:Graphic}}}">
<MenuItem
x:Name="miSelect"
Header="Select"
IsCheckable="True"
IsChecked="{Binding Selected, FallbackValue=False}"
/>
...
</ContextMenu>
</Path.ContextMenu>
</Path>
</Grid>
</ControlTemplate>
</esri:SimpleLineSymbol.ControlTemplate>
</esri:SimpleLineSymbol>
)
有什么想法吗?如果我正确理解了您的问题,似乎您在WPF中有一个常见的问题。解决方案是使用
路径的标记
属性
将数据上下文
传递到上下文菜单
。获取或设置当ContextMenu打开时相对于其定位的UIElement。试试这个:
<Path x:Name="Element" Fill="{x:Null}" Stroke="Navy" StrokeThickness="3"
StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round"
Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type
esri:Graphic}}}"><!--Use Binding.Path that you need for data here-->
<Path.ContextMenu>
<ContextMenu x:Name="popUpMenu" DataContext="{Binding PlacementTarget.Tag,
RelativeSource={RelativeSource Self}}"><!--Use PlacementTarget.Tag-->
<MenuItem x:Name="miSelect" Header="Select" IsCheckable="True"
IsChecked="{Binding Selected, FallbackValue=False}" />
...
</ContextMenu>
</Path.ContextMenu>
</Path>
...
解决方案是实现上下文菜单的打开偶数。在代码隐藏中,我将视图模型的实例分配给它的DataContext
<Path.ContextMenu>
<ContextMenu
Opened="PopUpMenu_OnOpened"
>
另一个挑战是获得点击图形和点击点。
解决方案是在视图模型中创建属性,并在LeftMouseDown和RightMouseDown上同时指定
private Graphic GetPolylineGraphic(ESRI.ArcGIS.Client.Geometry.Geometry geometry = null)
{
var drawLayer = Model.GetDrawLayer(MyMap, "Polyline");
var graphic = new Graphic
{
// clone the resourced PolylineSymbol (from Model)
Symbol = new SimpleLineSymbol
{
Color = PolylineSymbol.Color,
Width = PolylineSymbol.Width,
ControlTemplate = PolylineSymbol.ControlTemplate
}
};
if (geometry != null) graphic.Geometry = geometry;
graphic.MouseLeftButtonDown += GraphicOnMouseLeftButtonDown;
graphic.MouseRightButtonDown += GraphicOnMouseRightButtonDown;
drawLayer.Graphics.Add(graphic);
return graphic;
}
private Graphic m_clickedGraphic;
public Graphic ClickedGraphic
{
get { return m_clickedGraphic; }
set
{
if (!Equals(m_clickedGraphic, value))
{
m_clickedGraphic = value;
OnPropertyChanged(value);
}
}
}
private MapPoint m_clickedPoint;
public MapPoint ClickedPoint
{
get { return m_clickedPoint; }
set
{
if (m_clickedPoint != value)
{
m_clickedPoint = value;
OnPropertyChanged(value);
}
}
}
private void GraphicOnMouseRightButtonDown(object sender, MouseButtonEventArgs args)
{
//// This does not work because GraphicElement is internal!!!
//var s = args.Source;
//ClickedGraphic = ((GraphicElement)(e.Source)).Graphic;
//ClickedPoint = ((GraphicElement)(e.Source)).Origin;
ClickedGraphic = sender as Graphic;
ClickedPoint = MyMap.ScreenToMap(args.GetPosition(MyMap));
//// not here - else context menu won't pop!
//args.Handled = true;
}
private void GraphicOnMouseLeftButtonDown(object sender, MouseButtonEventArgs args)
{
var g = sender as Graphic;
if (g != null)
{
ClickedGraphic = g;
ClickedPoint = MyMap.ScreenToMap(args.GetPosition(MyMap));
// select/unselect the graphic on left click
if (g.Selected) g.UnSelect();
else g.Select();
args.Handled = true;
}
}
为了使一切正常工作,我必须克隆符号。在设计器中,在PlacementTarget.Tag中加上下划线,并在执行过程中出现错误“无法解析'System.Windows.UIElement'类型的数据上下文中的属性'Tag'”。我得到:System.Windows.data错误:4:无法找到与引用'RelativeSource FindAncestor'绑定的源,AncestorType='ESRI.ArcGIS.Client.Graphic',AncestorLevel='1'。BindingExpression:(无路径);DataItem=null;目标元素是'Path'(Name='element');目标属性是'Tag'(类型'Object')。我认为,这里有两个问题:1。“Path”是UIElement,它没有标记,除非我能够将其类型转换为Path。2.Path是GraphicElement的一部分,它被声明为内部,因此FindAncestor无法跨越。。。
private void PopUpMenu_OnOpened(object sender, RoutedEventArgs e)
{
var menu = sender as ContextMenu;
if (menu != null)
{
menu.DataContext = ViewModel;
}
}
private Graphic GetPolylineGraphic(ESRI.ArcGIS.Client.Geometry.Geometry geometry = null)
{
var drawLayer = Model.GetDrawLayer(MyMap, "Polyline");
var graphic = new Graphic
{
// clone the resourced PolylineSymbol (from Model)
Symbol = new SimpleLineSymbol
{
Color = PolylineSymbol.Color,
Width = PolylineSymbol.Width,
ControlTemplate = PolylineSymbol.ControlTemplate
}
};
if (geometry != null) graphic.Geometry = geometry;
graphic.MouseLeftButtonDown += GraphicOnMouseLeftButtonDown;
graphic.MouseRightButtonDown += GraphicOnMouseRightButtonDown;
drawLayer.Graphics.Add(graphic);
return graphic;
}
private Graphic m_clickedGraphic;
public Graphic ClickedGraphic
{
get { return m_clickedGraphic; }
set
{
if (!Equals(m_clickedGraphic, value))
{
m_clickedGraphic = value;
OnPropertyChanged(value);
}
}
}
private MapPoint m_clickedPoint;
public MapPoint ClickedPoint
{
get { return m_clickedPoint; }
set
{
if (m_clickedPoint != value)
{
m_clickedPoint = value;
OnPropertyChanged(value);
}
}
}
private void GraphicOnMouseRightButtonDown(object sender, MouseButtonEventArgs args)
{
//// This does not work because GraphicElement is internal!!!
//var s = args.Source;
//ClickedGraphic = ((GraphicElement)(e.Source)).Graphic;
//ClickedPoint = ((GraphicElement)(e.Source)).Origin;
ClickedGraphic = sender as Graphic;
ClickedPoint = MyMap.ScreenToMap(args.GetPosition(MyMap));
//// not here - else context menu won't pop!
//args.Handled = true;
}
private void GraphicOnMouseLeftButtonDown(object sender, MouseButtonEventArgs args)
{
var g = sender as Graphic;
if (g != null)
{
ClickedGraphic = g;
ClickedPoint = MyMap.ScreenToMap(args.GetPosition(MyMap));
// select/unselect the graphic on left click
if (g.Selected) g.UnSelect();
else g.Select();
args.Handled = true;
}
}