Silverlight开发中的疑难杂症:如何实现一个EditorBox
“HamSean”通过精心收集,向本站投稿了5篇Silverlight开发中的疑难杂症:如何实现一个EditorBox,这次小编给大家整理后的Silverlight开发中的疑难杂症:如何实现一个EditorBox,供大家阅读参考。
篇1:Silverlight开发中的疑难杂症:如何实现一个EditorBox
EditorBox就是一个具有编辑和展示两种状态的TextBox,因为在最近的工作和学习项目中 ,多次碰到了需要将一个TextBox以编辑和展示两种不同的样式存在,于是就想到了制作一个 这样的控件来提高生产效率,同时也尝试一下自定义控件的开发,该控件包括如下功能:
l 能在编辑和展示状态之间切换;
l 可以设置是否能够编辑;
l 在展示状态双击控件,进入到编辑状态(如果支持编辑);
l 在编辑状态,输入完文本,回车后进入展示状态;
l 提供一个Text属性供外部使用;
l 能够设置展示状态下文本样式(设置指定区间的文本的字体、字体大小、字体颜色等) ;
基本的实现思路是这样的:首先,定义两个TemplatePart,分别为TextBox和TextBlock类 型,用来表示编辑框跟展示框,文本格式的处理通过动态计算所设置的格式,然后添加多个 Run元素来实现;然后,定一个两个TemplateVisualState,用来实现编辑状态和展示状态之 间的切换。附加的Attribute声明如下:
[TemplatePart(Name = “PART_Editor”, Type = typeof(TextBox))]
[TemplatePart(Name = “PART_View”, Type = typeof(TextBlock))]
[TemplateVisualState(Name = “Edit”, GroupName = “CommonStates”)]
[TemplateVisualState(Name = “View”, GroupName = “CommonStates”)]
为了使控件使用者能够对样式进行更好的控制,这里定义了一个TextFormat类,与单个的 样式设置对应,里面包括字体、字体大小、字体颜色、样式应用的起始索引、应用的总长度 ,具体的类实现如下:
TextFormat
///
/// 文本格式
///
public class TextFormat : DependencyObject
{
///
/// 字体
///
public FontFamily FontFamily
{
get { return (FontFamily)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
public static readonly DependencyProperty FontFamilyProperty =
DependencyProperty.Register(“FontFamily”, typeof(FontFamily), typeof(TextFormat), new PropertyMetadata(default(FontFamily)));
///
/// 字体大小
///
public double FontSize
{
get { return (double)GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
public static readonly DependencyProperty FontSizeProperty =
DependencyProperty.Register(“FontSize”, typeof(double), typeof(TextFormat), new PropertyMetadata(10.0));
///
/// 字体颜色
///
public Brush Foreground
{
get { return (Brush)GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
public static readonly DependencyProperty ForegroundProperty =
DependencyProperty.Register(“Foreground”, typeof(Brush), typeof(TextFormat), new PropertyMetadata(new SolidColorBrush (Colors.Black)));
///
/// 样式应用的起始索引
///
public int StartIndex
{
get { return (int)GetValue(StartIndexProperty); }
set { SetValue(StartIndexProperty, value); }
}
public static readonly DependencyProperty StartIndexProperty =
DependencyProperty.Register(“StartIndex”, typeof(int), typeof(TextFormat), new PropertyMetadata(0));
///
/// 样式应用的长度
///
public int Length
{
get { return (int)GetValue(LengthProperty); }
set { SetValue(LengthProperty, value); }
}
public static readonly DependencyProperty LengthProperty =
DependencyProperty.Register(“Length”, typeof(int), typeof (TextFormat), new PropertyMetadata(0));
}
///
/// 文本格式集合
///
public class TextFormatCollection : ObservableCollection
{
}
之后是依赖属性的定义,除了之前提到过的文本格式集合以及当前选择的模式之外,还包 括对外提供的文本和是否允许编辑选项,同时在文本格式集合以及当前选择的模式改变时进 行文本格式化处理,依赖属性的定义如下:
Dependency Properties
#region Dependency Properties
///
/// 文本格式集合
///
public TextFormatCollection TextFormats
{
get { return (TextFormatCollection)GetValue(TextFormatsProperty); }
set { SetValue(TextFormatsProperty, value); }
}
public static readonly DependencyProperty TextFormatsProperty =
DependencyProperty.Register(“TextFormats”, typeof (TextFormatCollection), typeof(EditorBox), new PropertyMetadata(new PropertyChangedCallback(OnTextFormatsChanged)));
///
/// 文本
///
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(“Text”, typeof(string), typeof (EditorBox), new PropertyMetadata(string.Empty));
///
/// 是否允许编辑
///
public bool CanEdit
{
get { return (bool)GetValue(CanEditProperty); }
set { SetValue(CanEditProperty, value); }
}
public static readonly DependencyProperty CanEditProperty =
DependencyProperty.Register(“CanEdit”, typeof(bool), typeof (EditorBox), new PropertyMetadata(true));
///
/// 当前模式
///
public Mode CurrentMode
{
get { return (Mode)GetValue(CurrentModeProperty); }
set { SetValue(CurrentModeProperty, value); }
}
public static readonly DependencyProperty CurrentModeProperty =
DependencyProperty.Register(“CurrentMode”, typeof(Mode), typeof (EditorBox), new PropertyMetadata(Mode.View, new PropertyChangedCallback (OnCurrentModeChanged)));
#region Property Change Handler
private static void OnTextFormatsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as EditorBox).OnTextFormatsChanged(e.OldValue as TextFormatCollection, e.NewValue as TextFormatCollection);
}
///
/// 文本格式设置改变时,重新计算文本格式
///
///
///
protected virtual void OnTextFormatsChanged(TextFormatCollection oldCollection, TextFormatCollection newCollection)
{
if (oldCollection != null)
{
oldCollection.CollectionChanged -= new NotifyCollectionChangedEventHandler(TextFormats_CollectionChanged);
}
if (newCollection != null)
{
newCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(TextFormats_CollectionChanged);
}
//集合改变时重新计算文本格式
ProcessTextFormat;
}
///
/// 集合项改变时,重新计算文本格式
///
///
///
void TextFormats_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
ProcessTextFormat();
}
private static void OnCurrentModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as EditorBox).OnCurrentModeChanged((Mode)e.OldValue, (Mode) e.NewValue);
}
///
/// 从编辑模式切换到视图模式,进行文本格式计算
///
///
///
protected virtual void OnCurrentModeChanged(Mode oldMode, Mode newMode)
{
if (newMode == Mode.View)
{
ProcessTextFormat();
}
}
#endregion
由于使用了TemplatePart定义实现了界面与控件行为逻辑之间的解耦,那么自然的需要在 运行时拿到在样式中所定义的TemplatePart。这里通过重载OnApplyTemplate方法来实现子控 件的查找,以及相应的处理事件的附加,实现代码如下:
OnApplyTemplate
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
AttachToVisualTree();
}
///
/// 获取模板中的子控件,并附加处理
///
void AttachToVisualTree()
{
//获取模板中的子控件
_editor = GetChildControl
_viewer = GetChildControl
if (_editor != null)
{
//由于Silverlight的TextChanged事件只在Load之后才会触发,所以需 要在Load之后初始化文本格式
_editor.Loaded += new RoutedEventHandler (InitTextFormat);
//按下回车回到视图模式
_editor.KeyDown += new KeyEventHandler(EnterViewMode);
//设置绑定关系
_editor.Text = this.Text;
this.SetBinding(TextProperty, new Binding(“Text”) { Source = _editor, Mode = BindingMode.TwoWay });
}
ProcessTextFormat();
}
在实际测试时,这里发现了一个问题,当我在上面的方法中设置TextBox的Text属性后, 对应控件中注册的TextChanged事件并没有触发,经过多次的调试,发现似乎只有在控件Load 完之后进行的Text属性赋值操作,才会引起TextChanged事件;然而测试了WPF中的TextBox, 并没有发现有一样的问题,在网上也没有发现有类似的讨论,只好作罢。最后通过注册 TextBox的Loaded事件,并在里面重新进行了文本格式的处理。如果有对这个问题有所了解的 朋友,希望能够给我答疑解惑~
接下来是最重要的文本格式的处理,这部分的具体思路是这样的:
1.判断是否处于展示模式;
2.清楚原有的Inlines集合;
3.将TextFormats集合中的元素按照StartIndex从小到大进行排序;
4.循环处理TextFormats集合中的元素;
5.如果当前格式覆盖了前面的格式(StartIndex>LastIndex),则抛出异常;
6.如果当前格式与前面的格式之间有空隙,则将空隙单独设置为默认格式;
7.按照当前格式进行设置;
8.循环结束,如果还有剩余的文本,则全部用默认格式处理。
最后附上完整的代码以及默认的控件样式:
EditorBox
[TemplatePart(Name = “PART_Editor”, Type = typeof(TextBox))]
[TemplatePart(Name = “PART_View”, Type = typeof(TextBlock))]
[TemplateVisualState(Name = “Edit”, GroupName = “CommonStates”)]
[TemplateVisualState(Name = “View”, GroupName = “CommonStates”)]
public class EditorBox : Control
{
public const string PART_Editor = “PART_Editor”;
public const string PART_View = “PART_View”;
public const string VisualState_Edit = “Edit”;
public const string VisualState_View = “View”;
///
/// 模式
///
public enum Mode
{
///
/// 查看模式
///
View,
///
/// 编辑模式
///
Edit
}
#region Private Fields
private TextBox _editor;
private TextBlock _viewer;
#endregion
#region Dependency Properties
///
/// 文本格式集合
///
public TextFormatCollection TextFormats
{
get { return (TextFormatCollection)GetValue (TextFormatsProperty); }
set { SetValue(TextFormatsProperty, value); }
}
public static readonly DependencyProperty TextFormatsProperty =
DependencyProperty.Register(“TextFormats”, typeof (TextFormatCollection), typeof(EditorBox), new PropertyMetadata(new PropertyChangedCallback(OnTextFormatsChanged)));
///
/// 文本
///
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(“Text”, typeof(string), typeof (EditorBox), new PropertyMetadata(string.Empty));
///
/// 是否允许编辑
///
public bool CanEdit
{
get { return (bool)GetValue(CanEditProperty); }
set { SetValue(CanEditProperty, value); }
}
public static readonly DependencyProperty CanEditProperty =
DependencyProperty.Register(“CanEdit”, typeof(bool), typeof (EditorBox), new PropertyMetadata(true));
///
/// 当前模式
///
public Mode CurrentMode
{
get { return (Mode)GetValue(CurrentModeProperty); }
set { SetValue(CurrentModeProperty, value); }
}
public static readonly DependencyProperty CurrentModeProperty =
DependencyProperty.Register(“CurrentMode”, typeof(Mode), typeof(EditorBox), new PropertyMetadata(Mode.View, new PropertyChangedCallback(OnCurrentModeChanged)));
#region Property Change Handler
private static void OnTextFormatsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as EditorBox).OnTextFormatsChanged(e.OldValue as TextFormatCollection, e.NewValue as TextFormatCollection);
}
///
/// 文本格式设置改变时,重新计算文本格式
///
///
///
protected virtual void OnTextFormatsChanged(TextFormatCollection oldCollection, TextFormatCollection newCollection)
{
if (oldCollection != null)
{
oldCollection.CollectionChanged -= new NotifyCollectionChangedEventHandler(TextFormats_CollectionChanged);
}
if (newCollection != null)
{
newCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(TextFormats_CollectionChanged);
}
//集合改变时重新计算文本格式
ProcessTextFormat();
}
///
/// 集合项改变时,重新计算文本格式
///
///
///
void TextFormats_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
ProcessTextFormat();
}
private static void OnCurrentModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as EditorBox).OnCurrentModeChanged((Mode)e.OldValue, (Mode)e.NewValue);
}
///
/// 从编辑模式切换到视图模式,进行文本格式计算
///
///
///
protected virtual void OnCurrentModeChanged(Mode oldMode, Mode newMode)
{
if (newMode == Mode.View)
{
ProcessTextFormat();
}
}
#endregion
#endregion
public EditorBox()
{
this.DefaultStyleKey = typeof(EditorBox);
TextFormats = new TextFormatCollection();
//通过附加属性增加鼠标双击事件
this.SetValue(MouseEventHelper.MouseDoubleClickProperty, new MouseButtonEventHandler(MouseDoubleClick));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
AttachToVisualTree();
}
///
/// 获取模板中的子控件,并附加处理
///
void AttachToVisualTree()
{
//获取模板中的子控件
_editor = GetChildControl
_viewer = GetChildControl
if (_editor != null)
{
//由于Silverlight的TextChanged事件只在Load之后才会触发 ,所以需要在Load之后初始化文本格式
_editor.Loaded += new RoutedEventHandler (InitTextFormat);
//按下回车回到视图模式
_editor.KeyDown += new KeyEventHandler (EnterViewMode);
//设置绑定关系
_editor.Text = this.Text;
this.SetBinding(TextProperty, new Binding(“Text”) { Source = _editor, Mode = BindingMode.TwoWay });
}
ProcessTextFormat();
}
///
/// 第一次加载时,初始化文本格式
///
///
默认样式
xmlns=“schemas.microsoft.com/winfx//xaml/presentation”
xmlns:x=“schemas.microsoft.com/winfx/2006/xaml”
xmlns:local=“clr-namespace:YQL.CustomControlLibs” xmlns:d=“schemas.microsoft.com/expression/blend/” xmlns:mc=“schemas.openxmlformats.org/markup-compatibility/2006” mc:Ignorable=“d” >
效果预览:
www.bbniu.com/matrix/ShowApplication.aspx?id=70
篇2:Silverlight 2中多语言支持实现(下)
引言
苦笑不得的缺陷
在Silverlight 2中多语言支持实现(上)文章的最后,我们通过修改项目文件中SupportedCultures 来实现了多语言的支持,之所以能够成功,是因为前面的示例中只有两种语言English和Chinese,现在我 们再添加一个资源文件Strings.fr-FR.resx,让它能够支持French,如下图所示:
感谢我的同事Fabien帮我翻译为French,同样我们打开项目文件,在SupportedCultures中添加一种语 言文化fr-FR,我们可以用逗号或者分号来分割,如下代码所示:
现在我们解压xap文件,可以看到fr-FR、zh-CN资源文件都正确的打包在了xap文件中,如下图:
现在运行程序时,却发现中文语言文化无法显示,而法文能够正常显示:
这就是Silverlight 2 Beta 2在本地化方面支持的一个Bug,它只能够支持除默认语言之外的一种语言 。有朋友可能会问,既然能够支持除默认语言之外的一种语言,为什么在这个示例中不是中文,而是法文 呢?这主要是在SupportedCultures中设置的语言文化,在编译后,打包到AppManifest.xaml中添加 AssemblyPart时是按照语言文化的字母顺序排列的,所以会默认支持最上面一种语言文化:
好了,现在大家知道了在Silverlight 2 Beta 2中最多只能支持两种语言,但愿在RTM时该问题已经不 复存在,
另类多语言实现
现在我们再来看一种另类的多语言实现,即如果为一个Silverlight项目同时生成支持不同语言文化的 多个xap文件。我们可以在解决方案中添加一个新的Build Tag,如下图所示:
然后我们可以编辑Silverlight项目文件.csproj,可以在我们新建的Build Tag下面添加一项 SupportedCultures配置,并指定一种语言文化:
现在我们在Web测试项目中,配置一下xap文件的输出,只需要点击Change按钮就可以了,使 Configuration Specific Folders变为Yes,如下图所示:
这样可以我们通过修改Build Tag,来实现在Web测试项目中同时输出多个xap文件,而这些xap文件将 支持不同的语言,并且不会互相覆盖,如下图所示:
这样我们就可以用一个Silverlight项目来输出支持不同的语言文化的xap文件。
总结
篇3:Silverlight 2中实现Deep Zoom
概述
对于Deep Zoom想必大家都已经不陌生了,在Silverlight 2 Beta 1时已经提供了支持,并且提供了相 应的工具Deep Zoom Composer,Silverlight 2 Beta 2中对于Deep Zoom又有了很大的改进,现在支持基 于XML的DeepZoom集合的Manifest文件,Beta2还对DeepZoom加了可扩展的MultiScaleTileSource支持,更 新之后的Deep Zoom Composer可以使我们不用编写一行代码直接可视化的生成Deep Zoom应用。
在开始之前,请先确保安装了如下工具:
1.Silverlight Tools Beta 2 for Visual Studio
2.Deep Zoom Composer
总体来说,利用Deep Zoom Composer实现Deep Zoom应用分为如下三个步骤:导入、组合、导出。这三 个步骤在打开Deep Zoom Composer之后可以看到:
导入
第一步导入图片,可以点击“Add Image”按钮,一次选择想要导入的图片,如下图所示:
导入图片后效果如下图所示:
组合
经过了第一步导入图片后,我们可以对图片进行组合,选择需要加入到Deep Zoom应用中的图片,并调 整其位置及大小,如果在第一步没有导入图片,同样可以通过“Add Image”按钮来导入,
如下图所示:
我们方便的对图片的布局等进行调整,如下图所示:
导出
在对图片组合完成后,我们可以进行导出操作,并设置一些导出规则,如应用的名称,导出的路径等 ,这里Deep Zoom Composer提供了一个非常方便的选项,我们可以直接导出图片及生成Silverlight项目 ,如下图所示:
效果
经过以上三步之后,就可以直接生成Deep Zoom应用了,不用编写一行代码,生成的Silverlight项目 结构如下:
可以直接打开DeepZoomProjectTestPage.html查看最终的效果,如下所示:
实际应用
新浪音乐在微软 4 月 14 日 “Silverlight 锋芒彰显” 发布会中展示了新浪音乐最新的乐库原型, 其中应用了 Silverlight 中的 Deep Zoom 技术。更详细的情形大家可以参考这篇文章中的视频:
新浪音乐地图之 Deep Zoom 应用
blogs.msdn.com/jijia/archive/2008/04/16/sina-musicmap-details.aspx
结束语
篇4:Silverlight实现A*寻径算法
建议在新窗口中查看:
www.dotnet.pp.ru/silverlight/SilverlightAStar.html
花了几天的时间研究A*算法,总算是搞出来了,放上来给大伙儿瞧瞧。
点击“StartPoint”指定开始点,点击“EndPoint”指定目标点。点击“Impediment”指定不可通过区域。
GridSize设置节点大小,节点越小,容器中的节点就越多,填好后点Set保存设置。
Clear清除所有。
StartFindPath 开始寻径
Completed Tim 显示寻径所耗时间。
Diagonals 设置是否可以斜着走。
自我感觉速度不错。
下面说说算法的大致流程
首先定义两个列表
private List
penedList = new List
; //开启列表
private List
colsedList = new List
(); //关闭列表
开启列表中存储待检测节点。关闭列表中存储已检测节点。
从开始点开始,拿到开始点周围4或8个方向的节点,把他们添加进开启列表中。
G等于当前节点的父节点加上10或者14,水平或垂直方向加10,对角线方向加14
H等于当前节点的X的差与目标的的X的差、Y与目标点Y的差的绝对值的和。
F = G + H。
把当前节点从开启列表中删除。并添加进关闭列表中。以“F”值为依据从小到大排序,把F值最小的节点拿出来,重复以上过程。
大致流程是这样的。细节方面已经有一篇文章写的非常详细,在此也没有必要赘述了。
传送门:data.gameres.com/message.asp?TopicID=25439
最后放上算法的代码,不多。直接以文本形式发出来算了。
PathFinder
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
namespace SilverlightAStar
{
public class PathNote
{
public int F; //F = G + H
public int G;
public int H;
public int X;
public int Y;
public PathNote parentNote;
}
public class PathFinder
{
///
/// 矩阵
///
private byte[,] matrix;
///
/// 开始点
///
private Point startPoint;
///
/// 结束点
///
private Point endPoint;
///
/// 开启列表
///
private List
penedList = new List
(); //开启列表
///
/// 关闭列表
///
private List
colsedList = new List
(); //关闭列表
///
/// 是否允许斜线行走
///
private bool diagonals;
///
/// 方向
///
private sbyte[,] direction = new sbyte[8, 2] { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 }, { 1, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 } }; //默认方向
///
/// 构造函数
///
///
篇5:Silverlight数据绑定:怎样实现数据绑定
一个数据绑定可以通过 Binding 对象来描述,其中包含数据源,要绑定的属性路径(Path),目标,目 标属性等,
其中目标属性必须是依赖属性(DependencyProperty)。
为了说明方便,首先定义一个数据类:
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
例子1:
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
var persons = new List
();
for(var i=0; i< 5; i++)
{
persons.Add(new Person {Name = “Person ” + i.ToString(), Age = 20 + i});
}
list1.DataContext = persons;
}
}
这里仅指定了 list1 的 DataContext 属性 ,运行后发现页面没有显示。
如果在页面里改一改:
会发现绑定成功。但是数据项显示为默认的 Person 对象 ToString() 后的表示,不太友好。如下图 :
或者,也可以将后台代码改成:
list1.ItemsSource = persons;
而页面 markup 仍然是:
这样也能绑定成功。
这里的原因在于:ListBox 通过 ItemsSource 里的数据去填充数据项,所以直接给这个属性赋值是可 以的。
或者,通过空绑定语法 {Binding},指定 ItemsSource 属性绑定为数据源的对象本身(未指定绑定路 径)。而数据源就是通过 DataContext 获得的,并且这个属性的数据可以从父对象继承下来。
下面给 ListBox 指定列表项的数据模板,让它显示的好看一点:
显示如下:
还可以将 DataTemplate 定义到 App 的 Resource 里去,以便于重用,
App.xaml:
xmlns:x=“schemas.microsoft.com/winfx/2006/xaml”
x:Class=“SilverlightTestApp.App”
>
Page.xaml:
xmlns=“schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=“schemas.microsoft.com/winfx/2006/xaml”
Width=“400” Height=“300”>
运行后效果一样。
【Silverlight开发中的疑难杂症:如何实现一个EditorBox】相关文章:
3.用python实现的可以拷贝或剪切一个文件列表中的所有文件
10.成长中的一个小脚印作文






文档为doc格式