WPF後臺寫ControlTemplate總結

這段時間寫ControlTemplate的時候發現綁定的時候有些問題須要總結:html

實例ControlTemplate以下:express

<UserControl x:Class="ArcGISWpfMarkTest.TestSymbol"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
             xmlns:local="clr-namespace:ArcGISWpfMarkTest"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <esri:MarkerSymbol x:Key="Small" OffsetX="60" OffsetY="72">
            <esri:MarkerSymbol.ControlTemplate>
                <ControlTemplate>
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ImageNormal">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ImageSelected">
                                            <DiscreteObjectKeyFrame KeyTime="0"  Value="{x:Static Visibility.Visible}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="label0">
                                            <DiscreteObjectKeyFrame KeyTime="0"  Value="{x:Static Visibility.Visible}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="SelectionStates">
                                <VisualState x:Name="Unselected" />
                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ImageNormal">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ImageSelected">
                                            <DiscreteObjectKeyFrame KeyTime="0"  Value="{x:Static Visibility.Visible}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="label0">
                                            <DiscreteObjectKeyFrame KeyTime="0"  Value="{x:Static Visibility.Visible}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="0.2*"></RowDefinition>
                                <RowDefinition Height="0.2*"></RowDefinition>
                                <RowDefinition Height="0.8*"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Label  x:Name="label0" Visibility="Visible" Content="{Binding LabelContent1,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Grid.Row="0" BorderThickness="0.5" BorderBrush="White"  HorizontalContentAlignment="Center" Padding="0" Margin="0" Background="#2b5e93" VerticalContentAlignment="Center" Foreground="White"  Width="120" Height="20" FontSize="12"/>
                            <Label  x:Name="label1" Visibility="Visible" Content="{Binding LabelContent2,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Grid.Row="1" BorderThickness="0.5" BorderBrush="White" HorizontalContentAlignment="Center" Padding="0" Margin="0" Background="#2b5e93" VerticalContentAlignment="Center" Foreground="White" Width="120" Height="20" FontSize="12"/>
                            <Image Name="ImageNormal" Grid.Row="2" Source="/Images/small_police.png" Visibility="Visible"/>
                            <Image Name="ImageSelected" Grid.Row="2" Source="/Images/small_police_hit.png" Visibility="Hidden"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </esri:MarkerSymbol.ControlTemplate>
        </esri:MarkerSymbol>
    </UserControl.Resources>
    <Grid>
            
    </Grid>
</UserControl>

 

這個ControlTemplate是我定義的Arcgis runtime for wpf中MarkerSymbol的ControlTemplateapp

首先,我遇到第一個問題是:在map窗口的主程序中調用TestSymbol這個類的實例來引用它的ControlTemplate資源時候遇到兩個Label的Content沒法綁定佈局

狀況以下:TestSymbol類中我定義了LabelContent1和LabelContent2兩個屬性,在Map窗口的類中:this

TestSymbol testSymbol=new TestSymbol();spa

 testSymbol.TryFindResources("Small") as Symbol做爲一個Graphic點位的Symbol,這樣發現ControlTemplate定義的綁定寫法其實根本就錯誤的。.net

ControlTemplate做爲資源是被Map的主窗口調用,這樣它沿着可視樹查找的時候的DataContext就是Map的主窗口,因此LabelContent1和LabelContent2兩個屬性應該定義到設計

Map的主窗口類中,而且綁定應該這樣寫Content="{Binding LabelContent1,RelativeSource={RelativeSource AncestorType={x:Type Window}}}"code

 

可是這樣作的話對個人程序來講沒有意義,我不可能每一個點位都分別定義LabelContent1和LabelContent2兩個屬性,因此只能另外想辦法了。component

 

我從新定義了一個類用來存每一個點位的相關信息

using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Symbols;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ArcGISWpfMarkTest
{
    class TestElement:Graphic
    {
        private string manName;

        public string ManName
        {
            get { return manName; }
            set { manName = value; }
        }

        private string phoneNo;

        public string PhoneNo
        {
            get { return phoneNo; }
            set { phoneNo = value; }
        }
        public TestElement()
        {

        }
        public TestElement(string ManName,string PhoneNo)
        {
            this.ManName = ManName;
            this.PhoneNo = PhoneNo;
            ImageNormal = "pack://application:,,,/Source/Images/man32.png";
            ImageSelected = "/Source/Images/man_selected32.png";
            Symbol = GetMarkerSymbol() as Symbol;
        }

        public MarkerSymbol GetMarkerSymbol()
        {
            MarkerSymbol markerSymbol = new MarkerSymbol();
            markerSymbol.OffsetX = 60;
            markerSymbol.OffsetY = 72;
            markerSymbol.ControlTemplate = GetControlTemplate();
            return markerSymbol;
        }

        public string ImageNormal { get; set; }
        public string ImageSelected { get; set; }


        private ControlTemplate GetControlTemplate()
        {
            string template = "<ControlTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'><Grid><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name=\"SelectionStates\"><VisualState x:Name=\"Unselected\" /><VisualState x:Name=\"Selected\"><Storyboard><ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"ImageNormal\"><DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Hidden}\"/></ObjectAnimationUsingKeyFrames><ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"ImageSelected\"><DiscreteObjectKeyFrame KeyTime=\"0\"  Value=\"{x:Static Visibility.Visible}\"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Grid><Grid.RowDefinitions><RowDefinition Height=\"0.2 * \"></RowDefinition><RowDefinition Height=\"0.2 * \"></RowDefinition><RowDefinition Height=\"0.8 * \"></RowDefinition></Grid.RowDefinitions><Label Visibility=\"Visible\" Grid.Row=\"0\" BorderThickness=\"0.5\" BorderBrush=\"White\"  HorizontalContentAlignment=\"Center\" Padding=\"0\" Margin=\"0\" Background=\"" + "#2b5e93" + "\" VerticalContentAlignment=\"Center\" Foreground=\"White\" Content=\"" + ManName + "\" Width=\"" + "120" + "\" Height=\"" + "20" + "\" FontSize=\"" + "12" + "\"/><Label Visibility=\"Visible\" Grid.Row=\"1\" BorderThickness=\"0.5\" BorderBrush=\"White\" HorizontalContentAlignment=\"Center\" Padding=\"0\" Margin=\"0\" Background=\"" + "#2b5e93" + "\" VerticalContentAlignment=\"Center\" Foreground=\"White\" Content=\"" + PhoneNo + "\" Width=\"" + "120" + "\" Height=\"" + "20" + "\" FontSize=\"" + "12" + "\"/><Image Name=\"ImageNormal\" Grid.Row=\"2\" Source=\"" + ImageNormal + "\" Visibility=\"Visible\"/><Image Name=\"ImageSelected\" Grid.Row=\"2\" Source=\"" + ImageSelected + "\" Visibility=\"Hidden\"/></Grid></Grid></ControlTemplate>";
            var tem = XamlReader.Parse(template);
            return tem as ControlTemplate;
        }
    }
}

  這個TestElement類的關鍵思想是把xmal代碼定義成字符串格式,而後這個字符串是依賴於TestElement類的自身屬性而動態生成的,不一樣實例傳入的屬性不一樣,因此突破了xmal綁定機制的限制,能夠成功的爲每一個點位傳入不一樣的屬性值了,這個xmal代碼字符串經過如下代碼成功轉爲ControlTemplate了。

 var tem = XamlReader.Parse(template);
            return tem as ControlTemplate;

以上作法有點違背wpf思想設計初衷,我也是沒辦法才如此作的,誰叫個人WPF技能不夠高呢。。


在查找使用C#代碼後臺定義ControlTemplate的時候,發現這篇博文的方法也可行,只是再寫佈局的時候有些麻煩,我暫時尚未去實現
http://blog.csdn.net/zyloveyrf/article/details/6736844

還有一個問題總結:
在寫Image的資源路徑的時候遇到這樣一個問題:
在Demo程序中這樣定義Image的Resource可行

 "pack://application:,,,/Source/Images/man32.png" 絕對路徑
 "/Source/Images/man_selected32.png" 相對路徑

可是有時候上面的寫法無效,非要下面的寫法才行:

"pack://application:,,,/SDGPS_ManLayer;component/Source/Images/man32.png";
"pack://application:,,,/SDGPS_ManLayer;component/Source/Images/man_selected32.png";

這種狀況發生在個人圖層是單獨編譯成一個DLL,與MAP的主程序分離設計的。

我想多是程序資源集引用的相關問題,之後再作研究。

WPF的Resource路徑參考:

http://www.cnblogs.com/kushisei/p/5747708.html

https://msdn.microsoft.com/library/aa970069(v=vs.100).aspx

 

 

 

 

 

 

 

 

 

掛兩個外鏈,管理員請不要刪我文,如違規可聯繫我自行刪除,QQ:919497132

蘇州空調維修 蘇州冰箱維修 上海註冊公司

相關文章
相關標籤/搜索