Hulk' Den

in-depth thinking and keep moving.

简单实现弹出页更换头像的功能

  在Win 8应用里,对弹出页(Popup)的灵活操作必不可少,下面我们就来简单实现一个。

一、先让Popup弹出到指定位置

  先来看看效果图,如图[1]:

     

  下面是前端代码,代码段[1]:

<Grid Background="#0054a2">
    <Border Background="AliceBlue" Margin="40,40,1126,528" Width="150" Height="150">
        <Image x:Name="Img" Width="150" Height="150"/>
    </Border>
    <Button Margin="90,241,0,477" Content="更换头像" Width="100" Height="50" Click="Button_Click"></Button>
</Grid>

  接着是后台代码,代码段[2]:

private Popup headPopup;

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (headPopup != null)
    {
        headPopup.IsOpen = !headPopup.IsOpen;
    }
    else
    {
        headPopup = new Popup();
        //给headPopup添加内容
        HeadControl headControl = new HeadControl();
        headPopup.Child = headControl;
        //确定headPopup的弹出位置
        Rect imgRect = new Rect(new Point(0, 0), new Size(0, 0));
        GeneralTransform transform = this.Img.TransformToVisual(this);
        imgRect = transform.TransformBounds(imgRect);
        headPopup.HorizontalOffset = imgRect.Left + 150;
        headPopup.VerticalOffset = imgRect.Bottom + 130;
        //弹出Popup
        headPopup.IsOpen = true;
    }
}

   这里比较有趣的是确定Popup的弹出位置,我们是想在头像框的右下角弹出它。代码的具体实现方式是:通过控件Img的TransformToVisual方法获得一个通用的变换对象,这个变换对象可以把控件(也就是Img)变换成控件所对应的可视化图形,比如这里的Img就可以变换成一个矩形,通过这个矩形的属性我们就可以获得页面中控件Img各个边框的水平或者垂直位移,进而可以帮助我们确定Popup的位置。

 

二、弹出框中显示和选定头像

  上文中已经给Popup设定了子控件HeadControl,我们将在HeadControl里填充要显示的内容。这里有两个选择:

  1、在HeadControl中添加WebView控件,通过内嵌html页面来实现。

  2、在HeadControl中添加普通的Gridiew控件,用传统的方式绑定图片来显示。

  这里我们选择第一种方式,很显然,html页面可以更灵活的控制页面的样式,有助于我们做出更cool的应用!

  下面为HeadControl控件的前端代码,代码段[3]:

<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Background="#FFFFFFFF">
    <WebView x:Name="wvHead" HorizontalAlignment="Left" VerticalAlignment="Top"  Margin="0,0,0,-250" Height="420" Width="409" LoadCompleted="wvHead_LoadCompleted" ScriptNotify="wvHead_ScriptNotify" />
</Grid>

   代码中我们为WebView控件添加了LoadCompleted事件和ScriptNotify事件。还有个未列出的HeadControl的Loaded事件。其中:

   Loaded事件(HeadControl):当加载HeadControl控件时发生。如代码段[4]:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    //WebView加载指定的head.html页面
    this.wvHead.Navigate(new Uri("ms-appx-web:///Assets/head.html"));
}

   LoadCompleted事件(WebView):在WebView加载完成时发生。这里用来调用head.html中的js代码来给head.html页面写入内容,如代码段[5]:

private void wvHead_LoadCompleted(object sender, NavigationEventArgs e)
{
    //构造html,用来显示头像。
    StringBuilder sbSystem = new StringBuilder();
    string systemImg = "<li><img style=\"width:60px;height:60px;\" src=\"{0}\" onclick='FaceImageClick(\"{0}\")' alt=\"\" title=\"\"/></li>";
    string systemImg6 = "<li style=\"margin-right:0;\"><img style=\"width:60px;height:60px;\" src=\"{0}\" onclick='FaceImageClick(\"{0}\")' alt=\"\" title=\"\"/></li>";
    //加载记录有头像信息的xml
    var xml = XDocument.Load("Assets/Portraits/Portraits.xml");
    int syscount = 0;
    foreach (var ele in xml.Root.Elements("Portraits").Elements("file"))
    {
        syscount++;
        //每行放6个,第一个跟其他几个样式不太一样,单独处理。
        if (syscount % 6 == 0)
        {
            sbSystem.Append(string.Format(systemImg6, "/Assets/Portraits/" + ele.Attribute("name").Value));
        }
        else
        {
            sbSystem.Append(string.Format(systemImg, "/Assets/Portraits/" + ele.Attribute("name").Value));
        }
    }
    //调用head.html中的js方法将构造好的字符串写入。
    wvHead.InvokeScript("WriteSystemHtml", new string[] { sbSystem.ToString() });
}

   ScriptNotify事件(WebView):当包含在WebView中的内容使用JavaScript给应用程序传递字符串时发生。这里用来当head.html中图片的onclick被触发时通知后台代码哪个图片被点击了,以便于后台代码响应相应的事件。如代码段[6]:

public event EventHandler SelectEvent;
private void wvHead_ScriptNotify(object sender, NotifyEventArgs e)
{
    if (!string.IsNullOrEmpty(e.Value))
    {
        if (SelectEvent != null)
            SelectEvent(e.Value, null);
    }
}

  有人会有疑问,上面的SelectEvent在什么时候绑定方法呢?当然是在初始化HeadControl控件时,也就是在代码段[2]中加上:

headControl.SelectEvent += inputInfo;
private async void inputInfo(object sender, EventArgs e)
{
    //设置Image控件图像的源
    this.Img.Source = new BitmapImage(new Uri("ms-appx://" + sender, UriKind.RelativeOrAbsolute));
}

  注意:其实上面几个事件的关键点在于后台c#与html中的JavaScript的交互,掌握了这点,其他的就不是问题了!

  下面就来看看head.html里的具体实现吧,代码段[7]:

<script type="text/javascript">
    var $ = function (id) { 
        return (typeof id == 'string') ? document.getElementById(id) : id; 
    }
    //设置id为systempic的div的显示内容。
    var WriteSystemHtml = function (str) {
        $("systempic").focus();
        $("systempic").innerHTML = str;
    }
    var FaceImageClick = function (facePath) {
        //通知应用程序,向应用程序传递字符串。
        window.external.notify(facePath);
    }
</script>

 

  来看看最后的效果图吧! 图[2]:

      

   没错,我是一名德国球迷!哈哈。 html页面可以更生动的展现,就看你自己的需求了。

 

最近的文章

编码知识大杂烩

零、万物归宗ASCII码(American Standard Code for Information Interchange,美国标准信息交换代码),最原始最直观的表示方式,一个字节表示一个字符,一个字节=8位,那么一个字节就有256(2的8次方)种状态。这又分为标准ASCII和扩展ASCII,其中:标准ASCII(十进制0~127) 使用一个字节中除去最高位以外的7 位来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符。 Tips:标准ASCII中...…

编码继续阅读
更早的文章

将自定义的值类型用作字典的键,要特别注意什么?

  前天关注了老赵的微信公众号:赵人希。昨天就推送了一个快速问答,下面把我的答题经历跟大家分享,希望对于菜鸟同胞们有所帮助启发。  其实这个问题在他的博客里有专门的篇幅讲解,我猜到了,哈哈。但是大牛讲问题都是在一个高度上,水平差点的需要费点力气才能理解,而这个过程就是拉进我们与大牛距离的过程,用心总结下,才能不断强化自己靠近他们。一、通常的字典用法(熟练可直接略过)  在我平时的编码中,用的最频繁的就是代码段[1]:public class Example{ public stati...…

C# | .NET继续阅读