| Gustavo 的个人资料mentas日志列表SkyDrive | 帮助 |
|
11月24日 ItemsFeedHere's my proposal to break the limitations of current data/web feeds formats
Concepts:
<ItemsFeed Version="1.0"> <Collection Name="" Label=""> <Collection.Schema> <!-- Types: Boolean, Text, Number, Date, Bytes, Links Formats (samples): Text (mask), Number (D2), Date (dddd, dd MMMM yyyy HH:mm), Bytes (xml/jpg/pdf), Links (File/HTTP/CollectionName[ItemID]) IsFilter: True/False --> <Property Name="" Label="" Type="" Format="" IsFilter="" /> </Collection.Schema> <Collection.Template> <!-- Samples: xaml, html --> </Collection.Template> <!-- ID: ULong/Guid --> <Item ID="" Title="" Description="" Date="" State="" Author=""> <PropertyName></PropertyName> <!-- <PropertyName> <Link></Link> <Link></Link> <Link></Link> </PropertyName> --> </Item> </Collection> </ItemsFeed> 11月21日 APDC 2009Last week my team has been working for APDC 2009 congress. Microsoft Silverlight and Microsoft Surface has been used to create main event experiences.
Here's a resume...
Silverlight 3 (powered by FutureBox):
Developed by VIATECLA 11月15日 NavigableDynamicItem (Part II)A navigable version of DynamicItem. Now you can define forward/backward behaviors.
NavigableDynamicItem.cs public class NavigableDynamicItem : Control { private object temp_data = null;
public NavigableDynamicItem() { this.DefaultStyleKey = typeof(NavigableDynamicItem); }
public override void OnApplyTemplate() { base.OnApplyTemplate();
FrameworkElement root = (FrameworkElement)GetTemplateChild("LayoutRoot"); if (root == null) throw new Exception("'LayourRoot' element not found.");
((VisualStateGroup)VisualStateManager.GetVisualStateGroups(root)[0]).CurrentStateChanged += new EventHandler<VisualStateChangedEventArgs>(DynamicItem_CurrentStateChanged);
VisualStateManager.GoToState(this, "ForwardEnter", false); }
private void DynamicItem_CurrentStateChanged(object sender, VisualStateChangedEventArgs e) { if (e.NewState.Name == "ForwardLeave") { DispatcherTimer delay = new DispatcherTimer() { Interval = EnterDelay }; delay.Tick += delegate { DataContext = temp_data; temp_data = null;
VisualStateManager.GoToState(this, "ForwardEnter", false); delay.Stop(); delay = null; }; delay.Start(); } else if (e.NewState.Name == "ForwardEnter" && DataContext != null) VisualStateManager.GoToState(this, "Normal", true);
if (e.NewState.Name == "BackwardLeave") { DispatcherTimer delay = new DispatcherTimer() { Interval = EnterDelay }; delay.Tick += delegate { DataContext = temp_data; temp_data = null;
VisualStateManager.GoToState(this, "BackwardEnter", false); delay.Stop(); delay = null; }; delay.Start(); } else if (e.NewState.Name == "BackwardEnter" && DataContext != null) VisualStateManager.GoToState(this, "Normal", true); }
public void ChangeDataContextForward(object data) { temp_data = data;
DispatcherTimer delay = new DispatcherTimer() { Interval = LeaveDelay }; delay.Tick += delegate { VisualStateManager.GoToState(this, "ForwardLeave", DataContext != null); delay.Stop(); delay = null; }; delay.Start(); } public void ChangeDataContextBackward(object data) { temp_data = data;
DispatcherTimer delay = new DispatcherTimer() { Interval = LeaveDelay }; delay.Tick += delegate { VisualStateManager.GoToState(this, "BackwardLeave", DataContext != null); delay.Stop(); delay = null; }; delay.Start(); }
[Category("NavigableDynamicItem")] public TimeSpan EnterDelay { get; set; } [Category("NavigableDynamicItem")] public TimeSpan LeaveDelay { get; set; } } NavigableDynamicItem (Part I)A navigable version of DynamicItem. Now you can define forward/backward behaviors.
Generic.xaml <Style TargetType="local:NavigableDynamicItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:NavigableDynamicItem"> <Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="TransitionStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="00:00:00.5000000"/> <VisualTransition GeneratedDuration="00:00:00" To="ForwardEnter"/> <VisualTransition GeneratedDuration="00:00:00" To="BackwardEnter"/> </VisualStateGroup.Transitions> <VisualState x:Name="Normal"/> <VisualState x:Name="ForwardEnter"/> <VisualState x:Name="ForwardLeave"/> <VisualState x:Name="BackwardEnter"/> <VisualState x:Name="BackwardLeave"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBlock Text="{Binding }" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>TickerYou can use this panel as ItemsPanelTemplate on ItemsControl, ListBox, ...
Note: For a better control over delta FPS use a Storyboard instead DispatcherTimer.
public class Ticker : Canvas { public static readonly DependencyProperty DelayProperty; public static readonly DependencyProperty DeltaProperty;
private double pos = 0;
static Ticker() { DelayProperty = DependencyProperty.Register("Delay", typeof(TimeSpan), typeof(Ticker), new PropertyMetadata(TimeSpan.Zero)); DeltaProperty = DependencyProperty.Register("Delta", typeof(double), typeof(Ticker), new PropertyMetadata(2.0)); }
public Ticker() : base() { ClipToBounds = true;
Loaded += new RoutedEventHandler(Ticker_Loaded); }
public void Ticker_Loaded(object sender, RoutedEventArgs e) { foreach (FrameworkElement fe in Children) { pos = ActualWidth; Canvas.SetLeft(fe, ActualWidth); }
DispatcherTimer delay_timer = new DispatcherTimer() { Interval = Delay }; delay_timer.Tick += delegate { DispatcherTimer delta_timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(10) }; delta_timer.Tick += delegate { foreach (FrameworkElement fe in Children) { pos -= Delta; if (pos + fe.ActualWidth < 0) pos = ActualWidth;
Canvas.SetLeft(fe, pos); } }; delta_timer.Start();
delay_timer.Stop(); }; delay_timer.Start(); }
[Category("Ticker")] public TimeSpan Delay { get { return (TimeSpan)GetValue(DelayProperty); } set { SetValue(DelayProperty, value); } } [Category("Ticker")] public double Delta { get { return (double)GetValue(DeltaProperty); } set { SetValue(DeltaProperty, value); } } } WPF/SL binding converters (Part III)Plain text and image extraction from HTML...
public class TextConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return Regex.Replace((string)value, @"<[^>]*>", string.Empty).Trim(); }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion }
public class ImageConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { MatchCollection matches = Regex.Matches((string)value, "src=(?:\"|\')?(?<imgSrc>[^>]*[^/].(?:jpg|png))(?:\"|\')?");
if (matches.Count > 0) { if (parameter != null) return matches[int.Parse((string)parameter)].Groups[1].Value; else return matches[0].Groups[1].Value; }
return ""; }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion } WPF/SL binding converters (Part II)XmlDataProvider (Text, Number and DateTime) sorting...
public class TextSortConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { string[] args = ((string)parameter).Split(' ');
ICollection col = (ICollection)value;
List<string> aux = null;
if (args.Length == 2 && args[1] == "desc") { aux = (from item in col.Cast<XmlElement>() orderby item[args[0]].InnerText descending select item.InnerXml).ToList(); } else { aux = (from item in col.Cast<XmlElement>() orderby item[args[0]].InnerText select item.InnerXml).ToList(); }
int i = 0; foreach (XmlElement e in col) { e.InnerXml = aux[i]; i++; } }
return value; }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion }
public class NumericSortConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { string[] args = ((string)parameter).Split(' ');
ICollection col = (ICollection)value;
List<string> aux = null;
if (args.Length == 2 && args[1] == "desc") { aux = (from item in col.Cast<XmlElement>() orderby double.Parse(item[args[0]].InnerText.Replace(".", ",")) descending select item.InnerXml).ToList(); } else { aux = (from item in col.Cast<XmlElement>() orderby double.Parse(item[args[0]].InnerText.Replace(".", ",")) select item.InnerXml).ToList(); }
int i = 0; foreach (XmlElement e in col) { e.InnerXml = aux[i]; i++; } }
return value; }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion }
public class DateTimeSortConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { string[] args = ((string)parameter).Split(' ');
ICollection col = (ICollection)value;
List<string> aux = null;
if (args.Length == 2 && args[1] == "desc") { aux = (from item in col.Cast<XmlElement>() orderby DateTime.Parse(item[args[0]].InnerText) descending select item.InnerXml).ToList(); } else { aux = (from item in col.Cast<XmlElement>() orderby DateTime.Parse(item[args[0]].InnerText) select item.InnerXml).ToList(); }
int i = 0; foreach (XmlElement e in col) { e.InnerXml = aux[i]; i++; } }
return value; }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion } WPF/SL binding converters (Part I)Number round and DateTime format...
public class NumericConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (!string.IsNullOrEmpty((string)value) && parameter != null) { string num = Math.Round(double.Parse(((string)value).Replace(".", ",")), int.Parse((string)parameter)).ToString();
string[] dc = num.Split(','); int dc_num = 0; if (dc.Length == 2) dc_num = dc[1].Length;
for (int i = dc_num; i < int.Parse((string)parameter); i++) num += "0";
return num; } else return value; }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion }
public class DateTimeConverter : IValueConverter { #region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string dt = value.ToString();
ulong aux = 0; if (ulong.TryParse(dt, out aux)) { if (dt.Length == 8) return new DateTime(int.Parse(dt.Substring(0, 4)), int.Parse(dt.Substring(4, 2)), int.Parse(dt.Substring(6, 2))).ToString((string)parameter); else if (dt.Length == 10) return new DateTime(int.Parse(dt.Substring(0, 4)), int.Parse(dt.Substring(4, 2)), int.Parse(dt.Substring(6, 2)), int.Parse(dt.Substring(8, 2)), 0, 0).ToString((string)parameter); else if (dt.Length == 12) return new DateTime(int.Parse(dt.Substring(0, 4)), int.Parse(dt.Substring(4, 2)), int.Parse(dt.Substring(6, 2)), int.Parse(dt.Substring(8, 2)), int.Parse(dt.Substring(10, 2)), 0).ToString((string)parameter); else if (dt.Length == 14) return new DateTime(int.Parse(dt.Substring(0, 4)), int.Parse(dt.Substring(4, 2)), int.Parse(dt.Substring(6, 2)), int.Parse(dt.Substring(8, 2)), int.Parse(dt.Substring(10, 2)), int.Parse(dt.Substring(12, 2))).ToString((string)parameter); else return new DateTime(long.Parse(dt)).ToString((string)parameter); } else return DateTime.Parse(dt).ToString((string)parameter); }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); }
#endregion } 11月14日 DynamicItemThe ideia is something like "TransitionControl" concept (included in SL Toolkit), but using DataContext (Binding/Templating) and VisualStates. DynamicItem is a Control and must to be templated and the entering/leaving behaviors defined using the three states (Normal, Enter, Leave). Call ChangeDataContext method to change data and invoke transition states. If you need a composition between transition items, use two or more DynamicItem's (you can set an Enter/Leave delay time)... or simple prepare the Template and the DataContext to receive two items (new and old).
Generic.xaml <Style TargetType="local:DynamicItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:DynamicItem"> <Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="TransitionStates"> <VisualStateGroup.Transitions> <VisualTransition GeneratedDuration="00:00:00.5000000"/> <VisualTransition GeneratedDuration="00:00:00" To="Enter"/> </VisualStateGroup.Transitions> <VisualState x:Name="Normal"/> <VisualState x:Name="Enter"/> <VisualState x:Name="Leave"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBlock Text="{Binding }" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
DynamicItem.cs
public class DynamicItem : Control { private object temp_data = null;
public DynamicItem() { this.DefaultStyleKey = typeof(DynamicItem); }
public override void OnApplyTemplate() { base.OnApplyTemplate();
FrameworkElement root = (FrameworkElement)GetTemplateChild("LayoutRoot"); if (root == null) throw new Exception("'LayourRoot' element not found.");
((VisualStateGroup)VisualStateManager.GetVisualStateGroups(root)[0]).CurrentStateChanged += new EventHandler<VisualStateChangedEventArgs>(DynamicItem_CurrentStateChanged);
VisualStateManager.GoToState(this, "Enter", false); }
private void DynamicItem_CurrentStateChanged(object sender, VisualStateChangedEventArgs e) { if (e.NewState.Name == "Leave") { DispatcherTimer delay = new DispatcherTimer() { Interval = EnterDelay }; delay.Tick += delegate { DataContext = temp_data; temp_data = null;
VisualStateManager.GoToState(this, "Enter", false); delay.Stop(); delay = null; }; delay.Start(); } else if (e.NewState.Name == "Enter" && DataContext != null) VisualStateManager.GoToState(this, "Normal", true); }
public void ChangeDataContext(object data) { temp_data = data;
DispatcherTimer delay = new DispatcherTimer() { Interval = LeaveDelay }; delay.Tick += delegate { VisualStateManager.GoToState(this, "Leave", DataContext != null); delay.Stop(); delay = null; }; delay.Start(); }
[Category("DynamicItem")] public TimeSpan EnterDelay { get; set; } [Category("DynamicItem")] public TimeSpan LeaveDelay { get; set; } } 11月3日 ZoomboxBasic implementation of "Blendables Essentials Mix" concept for Silverlight.
Generic.xaml
<Style TargetType="local:Zoombox"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:Zoombox"> <Canvas x:Name="Container"> <ContentPresenter> <ContentPresenter.RenderTransform> <TransformGroup> <ScaleTransform x:Name="Zoom" /> <TranslateTransform x:Name="Pan" /> </TransformGroup> </ContentPresenter.RenderTransform> </ContentPresenter> </Canvas> </ControlTemplate> </Setter.Value> </Setter> </Style> Zoombox.cs
public class Zoombox : ContentControl { private Canvas container = null; private ScaleTransform zoom = null; private TranslateTransform pan = null;
public Zoombox() { this.DefaultStyleKey = typeof(Zoombox);
ZoomMargin = 10; }
public override void OnApplyTemplate() { base.OnApplyTemplate();
container = (Canvas)GetTemplateChild("Container"); zoom = (ScaleTransform)GetTemplateChild("Zoom"); pan = (TranslateTransform)GetTemplateChild("Pan"); }
public void ZoomTo(Rect rect) { rect.X = rect.X - ZoomMargin / 2; rect.Y = rect.Y - ZoomMargin / 2; rect.Width = rect.Width + ZoomMargin; rect.Height = rect.Height + ZoomMargin;
double factor = Math.Min(container.ActualWidth / rect.Width, container.ActualHeight / rect.Height); zoom.ScaleY = zoom.ScaleX = factor;
pan.X = (container.ActualWidth - rect.Width * factor) / 2 - rect.X * factor; pan.Y = (container.ActualHeight - rect.Height * factor) / 2 - rect.Y * factor; } public void ZoomTo(Rect rect, TimeSpan duration) { ZoomTo(rect, duration, null); } public void ZoomTo(Rect rect, TimeSpan duration, IEasingFunction func) { rect.X = rect.X - ZoomMargin / 2; rect.Y = rect.Y - ZoomMargin / 2; rect.Width = rect.Width + ZoomMargin; rect.Height = rect.Height + ZoomMargin;
double factor = Math.Min(container.ActualWidth / rect.Width, container.ActualHeight / rect.Height);
double panx = (container.ActualWidth - rect.Width * factor) / 2 - rect.X * factor; double pany = (container.ActualHeight - rect.Height * factor) / 2 - rect.Y * factor;
Storyboard sb = new Storyboard();
DoubleAnimation zoomx_anim = new DoubleAnimation() { To = factor, Duration = duration, EasingFunction = func }; Storyboard.SetTarget(zoomx_anim, zoom); Storyboard.SetTargetProperty(zoomx_anim, new PropertyPath("ScaleX"));
DoubleAnimation zoomy_anim = new DoubleAnimation() { To = factor, Duration = duration, EasingFunction = func }; Storyboard.SetTarget(zoomy_anim, zoom); Storyboard.SetTargetProperty(zoomy_anim, new PropertyPath("ScaleY"));
DoubleAnimation panx_anim = new DoubleAnimation() { To = panx, Duration = duration, EasingFunction = func }; Storyboard.SetTarget(panx_anim, pan); Storyboard.SetTargetProperty(panx_anim, new PropertyPath("X"));
DoubleAnimation pany_anim = new DoubleAnimation() { To = pany, Duration = duration, EasingFunction = func }; Storyboard.SetTarget(pany_anim, pan); Storyboard.SetTargetProperty(pany_anim, new PropertyPath("Y"));
sb.Children.Add(zoomx_anim); sb.Children.Add(zoomy_anim); sb.Children.Add(panx_anim); sb.Children.Add(pany_anim); sb.Begin(); }
public double ZoomCache { get { if (((UIElement)Content).CacheMode == null) return 0; else return ((BitmapCache)((UIElement)Content).CacheMode).RenderAtScale; } set { if (value == 0) ((UIElement)Content).CacheMode = null; else ((UIElement)Content).CacheMode = new BitmapCache() { RenderAtScale = value }; } } public double ZoomMargin { get; set; } } |
|
|