| Comments

One of the great things I like about some of our platform products is that they are building in extensibility more and more.  Take Windows Live Writer as an example.  It’s no secret on this blog that I’ve got a geek affair with that tool.  I use it daily and have customized it (via plugins) and my blogging platform (Subtext) to make it even more of a best experience for me for web authoring.

Writing plugins for Writer has been a lot of fun and a great way to get the functionality I want/need into a workflow without having a different utility to work in.  Another one of these tools has been Expression Encoder 2 which I’ve been using a bit more lately.  Expression Encoder is a tool that enables the encoding of audio/video assets into VC-1 formats and H.264/AAC formats.  It’s a really simple tool to use and also comes with several Silverlight player templates that you can choose as a part of your output.  In one click you can have your HD home movie encoded and a rich playback experience developed for you as well.  I’ve wrote several times about Encoder, templates, etc. before and you can see some of them here:

With no shortage of information on how to do it, I got home last night and began cranking one out.  I’ve been using Amazon’s S3 web services for a while and have really grown to like it a lot.  One of the Live Writer extensions I spoke of earlier is a plugin for S3 for Live Writer that Aaron Lerch helped out with as well!  I though I should extend Encoder so that I’d have a one click publishing point to my S3 account instead of having to use S3Fox all the time (which is an awesome tool btw).

So after getting home from a user group I started cranking one out, figuring out the nuances and just coding something together.  A few hours later I came up with what I’m calling 1.0 beta of my plugin.

It’s not a fancy UI, but it doesn’t need to be, it serves a purpose: enable publishing of Encoder output directly to an Amazon S3 bucket in one click.  That’s it.  Encoding just media?  No problem.  Adding a template?  Not a problem either.  You simply need to enter your Amazon S3 account information and enter a bucket.  If the bucket isn’t there, it will attempt to create it.  You can also list your current buckets if you forgot them.

There are likely indeed a few problems and some fit-n-finish needed.  I am positive the error handling needs to be refined as well as it could probably benefit from some more efficient threading handling.  The cool think about the Encoder publishing plugins is that they are WPF user controls, so it gave me a chance to work with more XAML.

At any rate, even in the current form (which isn’t perfect but seems to be working for the specific need I built it for -- “works on my machine” warranty applies here) I wanted to share it out for any others to use and hopefully give feedback and contribute.  It’s available as a Ms-PL licensed project with source code and you can get it on CodePlex: Amazon S3 Encoder Publishing Plugin.  I hope you like it and can give feedback.  Please if you find issues log them in the Issue Tracker for the project so they are trackable.

| Comments

The source code for the Silverlight 2 controls was just published!  This is the source for the controls as shipped in the runtime and the SDK.  When you download the project you’ll see the structure:

Image of source project tree in Visual Studio

The source, released under the Microsoft Public License (Ms-PL), includes the source for the following controls in the runtime:

    • ButtonBase
    • Button
    • HyperlinkButton
    • CheckBox
    • RadioButton
    • ToggleButton
    • RangeBase
    • ProgressBar
    • Slider
    • ScrollBar
    • Thumb

and the following from the SDK (part of the Silverlight Tools for Visual Studio):

    • Calendar
    • DatePicker
    • DataGrid
    • TabControl
    • GridSplitter

Unit tests for the SDK controls have also been included as well!

With the release of this source code as well as having access to the source for the Silverlight Toolkit, you should have some great base implementations to extend and learn from!  Get the code here: Source code for Silverlight 2 controls.

| Comments

This is a public service announcement for my Flickr4Writer project.  It was recently brought to my attention that Flickr has some privacy settings that users can opt-in for in their account to protect their images.  Some users felt that my plug-in for Writer was not honoring these settings.  Truly, I didn’t know about them.  You can read the thread on the discussion lists here if you are so inclined.  For me it came down to a couple of items:

    • Flickr enables users to set a flag to prevent “blogging” of their images
    • Flickr enables users to be hidden from 3rd Party/API searches

First, a note on the “blogging” flag.  This is a setting under your Flickr account privacy tab labeled Who can blog your photos or videos?.  To me, this setting is a little misleading because the description of it actually reads:

This means that anyone who does not match at least the contact level you select will not be able to see the "Blog This" button. (Source: http://www.flickr.com/account/prefs/blogging/?from=privacy 07 NOV 2008)

This setting is clearly for the “Blog This” functionality that shows up if you are logged into Flickr as a non-anonymous user and browse photos.  There is some functionality for them to integrate directly with your blog engine to do some one-click blogging of photos and videos.  Because of the way the setting is named however, some users interpret “blogging” in the broader sense.  flickr4writer was challenged as one violating the principal of this setting.  Since the setting ONLY enables authenticated users to even blog (the setting options go from any Flickr user (non-anonymous) to your specific friends/family settings.  flickr4writer does not use any authentication, so browsing any photos has the appearance to violate this term if the plugin enables an anonymous user to browse and select photos in a tool that is build for “blogging.”  While I draw the correlation that flickr4writer is basically a shell to the web site and does not do anything different than an anonymous user being able to browse and grab an image URL, it is the essence of the rule that I was alleged to violate.  One challenge here is also that the API is poorly designed in this regard because the “canblog” setting is returned only at the photo level even though it is an uber setting for the user’s account.  I think it should be a filter param of the photos.search API call.

The second setting about 3rd Party/API blocking from searches gets even more interesting.  First, this totally makes sense.  Again, it was a setting I wasn’t aware of.  You can change your setting under a section titled Hide your photostream from searches on 3rd party sites that use the API?  Great.  You’d think that once a user selected this setting that any search would filter out their photos/vidoes at the API level right?  Wrong.  flickr4writer uses photos.search calls to query data (actually technically the library that Flickr4Writer uses does).  Again, by definition of this API, only public searchable photos will be returned.  UNLESS you specify a user name.  What?!?!  Yes, that’s right…if you specifc a user name, their results will come back in the API call.  Read that again.  If you specify a user name in flickr.photos.search it will not honor the user’s privacy setting.  So this sucks for me as an API developer/consumer who wants to honor those settings.

So on to the resolutions.  First, I added authentication.  flickr4writer now requires you to have a valid Flickr account to even use it (their accounts are free).  This helps with the first part about blogging.  If a user has specified they do not want their content to be blogged, I honor that and will alert the flickr4writer user with a message that the user they searched prevents blogging and no search results will display.  I feel that this complies with that setting within my application.  If a user wants to bypass my app and copy/paste the URL to the photo/video still…that’s Flickr’s problem now, not mine.  Adding authentication also enabled me to comply with the blogging settings of users because it identifies who the user is and whether or not they can blog the content.

The second thing I modified was to only return content that had Creative Commons or No known license attributes.  This actually makes sense and I needed to do it for a while.  The licenses I filter for are identified in the flickr.photos.licenses.getInfo API.  So if a user has content that is “All rights reserved” then it will no longer show up in the search…even if you are the owner of that content.  I’m interested in feedback on this one if you think I should do a check to see if you are the owner and allow you to see licensed content…leave a comment on how you feel about this one.

For the setting of hiding from 3rd parties…I cannot resolve this.  There is no setting for me to look at.  I’m quite disappointed that Flickr isn’t doing this at the API level as I think that they are violating the user preferences by enabling a loophole.  Should they enable a setting for this (I think they just need to fix the API), I will enable my application to comply even more.  Please if you are a Flickr user who has set this privacy setting, let Flickr know that you want it to be honored.

The authentication adds some initial screens to the use of flickr4writer.  When you launch the plug-in from within Writer, you’ll now see some prompts to authorize the application with Flickr.  There will be a button that will take you to Flickr to authorize the action.  This is only required one time and you won’t see it anymore unless you de-authorize the application on your account (which you have the complete control to perform).

Please upgrade to the latest version.  You will have to uninstall any previous version before installing, but will not lose any settings.  Thanks for your assistance in helping keeping flickr4writer compliant.

| Comments

Today at Microsoft PDC, Scott Guthrie demonstrated some of the new controls that have been provided as a part of the Silverlight Toolkit

The Silverlight Toolkit was what was previously named the Silverlight Control Pack in the press release when the runtime was released. 

This toolkit provides a set of controls and themes for Silverlight 2.  In this initial release, they are:

    • AutoCompleteBox
    • Chart
    • DockPanel
    • Label
    • Expander
    • TreeView
    • UpDown
    • ViewBox
    • WrapPanel
    • ImplicitStyleManager
    • Themes (6): ExpressionDark/Light, RanierOrange/Purple, ShinyBlue/Red

These controls are released as an initial version, with tests and available with Ms-Pl licensing on Codeplex.  Of particular interest to me is the Charting components.  Typically available at cost with other platforms, the Silverlight team is providing a base set of Charting controls with source for you to implement, customize and ship with your products.  What is great about this type of control is an implementation with data binding as well, especially with an ObservableCollection.  With this combination you can have a powerful real-time experience updating information without having to re-paint the entire chart or do any postbacks for the app as well.

Let’s take a quick simple sample of what I’m talking about.  To use any of the controls in the toolkit, simply add a reference to the assembly in your project and then use the xmlns declaration at the root of your implementation.  I’m going to use “toolkit” as mine like this:

   1: xmlns:chart="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;assembly=Microsoft.Windows.Controls.DataVisualization"

Then we can use the chart in our XAML along with some other code.  Here I have a Slider and a TextBlock as well showing the value of the Slider as you change it.  I’ve also added the chart series and provided some data binding syntax for the series data:

   1: <UserControl
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     x:Class="SLToolkitDemo.Page"
   5:     xmlns:chart="clr-namespace:Microsoft.Windows.Controls.DataVisualization.Charting;assembly=Microsoft.Windows.Controls.DataVisualization"
   6:     Width="800" Height="600">
   7:     <Grid x:Name="LayoutRoot" Background="White">
   9:         <StackPanel Orientation="Vertical" Margin="15">
  10:             <TextBlock Text="Change Line Value"/>
  11:             <Slider x:Name="LineValueSlider" Value="12" Maximum="150" Minimum="0" />
  12:             <TextBlock x:Name="SliderValue" />
  13:             <chart:Chart Height="200" LegendTitle="Item" Title="My Simple Data-bound Chart" 
  14:                          x:Name="MyBarChart">
  15:                 <chart:Chart.Series>
  16:                     <chart:ColumnSeries x:Name="MySalesChartData" Title="Sales of Charts" 
  17:                                         ItemsSource="{Binding}"
  18:                          IndependentValueBinding="{Binding ChartType}"
  19:                          DependentValueBinding="{Binding ChartSaleCount}"/>
  20:                 </chart:Chart.Series>
  21:             </chart:Chart>
  22:             <chart:Chart Height="200" Title="My Simple Pie Chart" x:Name="MyPieChart">
  23:                 <chart:Chart.Series>
  24:                     <chart:PieSeries ItemsSource="{Binding}" 
  25:                                      IndependentValueBinding="{Binding ChartType}"
  26:                                      DependentValueBinding="{Binding ChartSaleCount}" />
  27:                 </chart:Chart.Series>
  28:             </chart:Chart>
  29:         </StackPanel>
  31:     </Grid>
  32: </UserControl>

Now in my code I’ve hacked together some simulation of the ObservableCollection changing the value of the Line data to the value of the slider.  Because I implemented my class of Sale with INotifyPropertyChanged the default databinding of OneWay enables my target to be updated once any of my source (salesData) changes.  Here’s the full code:

   1: using System;
   2: using System.Windows;
   3: using System.Windows.Controls;
   4: using System.Windows.Documents;
   5: using System.Windows.Ink;
   6: using System.Windows.Input;
   7: using System.Windows.Media;
   8: using System.Windows.Media.Animation;
   9: using System.Windows.Shapes;
  10: using System.Collections.ObjectModel;
  11: using Microsoft.Windows.Controls.DataVisualization.Charting;
  13: namespace SLToolkitDemo
  14: {
  15:     public partial class Page : UserControl
  16:     {
  17:         ObservableCollection<Sale> salesData;
  19:         public Page()
  20:         {
  21:             // Required to initialize variables
  22:             InitializeComponent();
  23:             salesData = SalesData.GetData();
  24:             Loaded += new RoutedEventHandler(Page_Loaded);
  25:         }
  27:         void Page_Loaded(object sender, RoutedEventArgs e)
  28:         {
  29:             ColumnSeries column = MyBarChart.Series[0] as ColumnSeries;
  30:             PieSeries pie = MyPieChart.Series[0] as PieSeries;
  31:             column.ItemsSource = salesData;
  32:             pie.ItemsSource = salesData;
  33:             LineValueSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(LineValueSlider_ValueChanged);
  34:         }
  36:         void LineValueSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
  37:         {
  38:             salesData[2].ChartSaleCount = Convert.ToInt32(e.NewValue);
  39:             SliderValue.Text = e.NewValue.ToString();
  40:         }
  41:     }
  42: }

And here is the SalesData.cs class:

   1: using System;
   2: using System.Net;
   3: using System.Windows;
   4: using System.Windows.Controls;
   5: using System.Windows.Documents;
   6: using System.Windows.Ink;
   7: using System.Windows.Input;
   8: using System.Windows.Media;
   9: using System.Windows.Media.Animation;
  10: using System.Windows.Shapes;
  11: using System.Collections.ObjectModel;
  12: using System.Collections.Generic;
  13: using System.ComponentModel;
  15: namespace SLToolkitDemo
  16: {
  17:     public class SalesData
  18:     {
  19:         public static ObservableCollection<Sale> GetData()
  20:         {
  21:             ObservableCollection<Sale> sales = new ObservableCollection<Sale>();
  23:             sales.Add(new Sale() { ChartSaleCount = 100, ChartType = "Bar" });
  24:             sales.Add(new Sale() { ChartSaleCount = 73, ChartType = "Pie" });
  25:             sales.Add(new Sale() { ChartSaleCount = 12, ChartType = "Line" });
  26:             sales.Add(new Sale() { ChartSaleCount = 24, ChartType = "Spline" });
  28:             return sales;
  29:         }
  30:     }
  32:     public class Sale : INotifyPropertyChanged
  33:     {
  34:         private int _count;
  35:         public string ChartType { get; set; }
  36:         public int ChartSaleCount
  37:         {
  38:             get { return _count; }
  39:             set
  40:             {
  41:                 _count = value;
  42:                 NotifyPropertyChanged("ChartSaleCount");
  43:             }
  44:         }
  46:         #region INotifyPropertyChanged Members
  48:         public event PropertyChangedEventHandler PropertyChanged;
  50:         public void NotifyPropertyChanged(string propertyName)
  51:         {
  52:             if (PropertyChanged != null)
  53:             {
  54:                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  55:             }
  56:         }
  57:         #endregion
  58:     }
  59: }

The result of which is when I move the slider to perhaps simulate real-time data, I see the data binding change in the chart represented here:

As you can see I have two charts using the same ObservableCollection<T>, so changing the data, changes both of the charts without any extra effort. 

Charting along with some of the other controls brings this really, really nice addition to Silverlight 2.  I hope you find them valuable.  We’ll be using them in projects and digging deeper (especially in charting) on the Silverlight Community Site, so I hope you visit there.  You can download the actual sample project for this file as well right here: SLToolkitDemo.zip

If you liked this post, please consider subscribing to the feed for more like it.  Justin Angel is also a program manager for the toolkit that you should check out some depth posts from him on the controls as well.  You can visit the samples site here showing you a gallery of the controls in implementation.

| Comments

In the early days of Silverlight 2, one of the included controls was the WatermarkedTextBox.  In Beta 2 the control was removed from the runtime for among other things, WPF compatibility.  The control source code was made available for people to look at as it was referenced in a few projects, namely ScottGu’s Digg sample application.  There was hinting about future plans but nothing concrete. 

Now that Silverlight 2 is released, the control is not there :-).  I’ve gotten enough requests about it that I wanted to provide some action for you.  First, let me say that there are no concrete plans for WatermarkedTextBox at this time that I have to share.  I’m not saying there isn’t plans, but just that none at a point to make any worthwhile announcements.  Perhaps something like this would show up in the Silverlight Toolkit, but at this time no plans have been defined.

Again, as I’ve received enough requests, I’ve modified the source code for WatermarkedTextBox for Silverlight 2 release and am making it available for you to consume.  The code has been updated for use in Silverlight 2 and also updated to reflect the default styling of the released controls (namely to match TextBox).

If you aren’t familiar with the concept, it’s basically a TextBox with a value you can set for some helper text if the value is not set.  Typically you use this when you want to provide “prompt” text for some input, as an example here:

As you can see the TextBox provides a '”faded” default text that isn’t the TextBox.Text property of the control, but rather the Watermark property of this control.  Once data is entered in the control, the watermark goes away.  As long as data is input the watermark isn’t displayed…if the value is empty, the watermark displays.  Simple enough.

The XAML for the above looks like this:

   1: <UserControl x:Class="WatermarkTester.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:local="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls.WatermarkedTextBox"
   5:     Height="300" Width="600" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
   6:     <Grid x:Name="LayoutRoot" Background="White">
   7:         <StackPanel Orientation="Vertical">
   8:             <Grid Margin="15">
   9:                 <Grid.RowDefinitions>
  10:                     <RowDefinition Height="Auto" />
  11:                     <RowDefinition Height="Auto" />
  12:                     <RowDefinition Height="Auto" />
  13:                     <RowDefinition Height="Auto" />
  14:                 </Grid.RowDefinitions>
  15:                 <Grid.ColumnDefinitions>
  16:                     <ColumnDefinition Width="Auto" />
  17:                     <ColumnDefinition Width="Auto" />
  18:                 </Grid.ColumnDefinitions>
  19:                 <TextBlock Text="First Name:" Margin="5" Grid.Column="0" Grid.Row="0" />
  20:                 <local:WatermarkedTextBox Grid.Column="1" Grid.Row="0" Watermark="Enter your first name here..."/>
  21:                 <TextBlock Text="Last Name:" Margin="5" Grid.Column="0" Grid.Row="1" />
  22:                 <local:WatermarkedTextBox Grid.Column="1" Grid.Row="1" Watermark="Enter your last name here..." />
  23:                 <TextBlock Text="Phone Number:" Margin="5" Grid.Column="0" Grid.Row="2" />
  24:                 <local:WatermarkedTextBox Grid.Column="1" Grid.Row="2" Watermark="(xxx) xxx-xxxx" />
  25:             </Grid>
  26:         </StackPanel>
  27:     </Grid>
  28: </UserControl>

Note the xmlns:local declaration in the user control which references the binary.

The control is also Blend compatible if you want to change the style/control template so if you wanted to change the Watermark color or something like that you could easily do that with Blend:

So if you’ve been looking for this control, here you go.  You can download the bits here:

The source is available as Ms-Pl.  Hope this helps!