CoreCLR's Blog

Archive for November, 2009

How to expand TreeViewItems from right to left in Silverlight

Posted by coreclr on November 28, 2009

In this post I am going to show how we can change the Silverlight TreeView Template to support expanding TreeViewItems from right to left.
The text on the items should still be left-to-right and the text should be right alligned.

First we will build a normal TreeView with some data.

We define a HierarchicalDataTemplate:

<UserControl.Resources>
      <common:HierarchicalDataTemplate x:Key="MyHierarchicalTemplate" ItemsSource="{Binding Items}" >
          <TextBlock Text="{Binding Title}" />
      </common:HierarchicalDataTemplate>
  </UserControl.Resources>

And this is the TreeView that will use the HierarchicalDataTemplate:

<controls:TreeView VerticalAlignment="Stretch" 
          x:Name="treeView"                                                                  
          ItemTemplate="{StaticResource MyHierarchicalTemplate /> 

Then we define a simple class to hold the data:

public class DataItem
    {
      public string Title { get; set; }
      public ObservableCollection<DataItem> Items { get; set; }

      public DataItem(string title, params DataItem[] items)
      {
          this.Title = title;
          ObservableCollection<DataItem> itemsObservableCollection =
              new ObservableCollection<DataItem>();

          foreach (var item in items)
            itemsObservableCollection.Add(item);

         Items = itemsObservableCollection;
      }
    }


And in our MainPage we populate the TreeView with some data:

public partial class MainPage : UserControl
    {
        ObservableCollection<DataItem> itemsSource;
        public MainPage()
        {
            InitializeComponent();
            AddData();
            treeView.ItemsSource = itemsSource;
        }

        private void AddData()
        {
            itemsSource = new ObservableCollection<DataItem>()
            {
                 new DataItem("Europe",
                    new DataItem("Denmark"),
                    new DataItem("Norway"),
                    new DataItem("Sweden")),
                  new DataItem("USA",
                    new DataItem("New York",
                        new DataItem("Albany"))),
            };
        }
    }

When we run this, we get a simple TreeView like this:

image

So far, so good. Now lets change the Template so we can get the TreeView to display the items from Right to Left.

We open Blend and edit the ItemContainerStyle Template:

image

First set HorizontalContentAlignment and HorizontalAlignment to right:

<Setter Property="HorizontalContentAlignment" Value="Right"/>
<Setter Property="HorizontalAlignment" Value="Right"/>


Now locate the Grid element, and change the definition to this:

<Grid.ColumnDefinitions>
   <ColumnDefinition Width="Auto"/>
   <ColumnDefinition Width="15"/>
   <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
   <RowDefinition Height="Auto"/>
   <RowDefinition Height="*"/>
</Grid.RowDefinitions>

Now located the Selection Rectangle element and set these two properties:

Grid.Column="0"
HorizontalAlignment="Right"


Now located the Header Button element and set these properties:

Margin="0,0,10,0"
Grid.ColumnSpan="2"
HorizontalAlignment="Right"

Next locate the ContentPresenter and set HorizontalAlignment:

HorizontalAlignment="Right"

Then locate the ItemsPresenter element and set these properties:

Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0,0,10,0"
HorizontalAlignment="Right"
Visibility="Collapsed"

Now Locate the ExpanderButton and set these properties:

VerticalAlignment="Stretch" 
HorizontalAlignment="Right" 
RenderTransformOrigin="0.5,0.5" 
Grid.Column="1"

Now we will use a RotateTransform to rotate the ExpanderButton. Add this:

<ToggleButton.RenderTransform>
           <TransformGroup>
              <ScaleTransform/>
              <SkewTransform/>
              <RotateTransform Angle="-180"/>
              <TranslateTransform/>
           </TransformGroup>
</ToggleButton.RenderTransform>

Now add a RotateTransform to the CheckedVisual Path element. We rotate that –90.

<Path.RenderTransform>
  <TransformGroup>
     <ScaleTransform/>
     <SkewTransform/>
     <RotateTransform Angle="-90"/>
     <TranslateTransform/>
  </TransformGroup>
</Path.RenderTransform>

That’s it!

Set the ItemContainerStyle on the TreeView to our new Template:

ItemContainerStyle="{StaticResource RightToLeftViewItemStyle}"

Run and you should see the Items expanding from right to left with the text alligned to the right:

image

Get the code here.

(rename it to .zip)

Advertisements

Posted in .NET, Silverlight | Leave a Comment »

Silverlight 4 kursus

Posted by coreclr on November 26, 2009

Fra den 1. til 4. februar 2010 afholder Thomas Martinsen og undertegnede et Silverlight 4 kursus.

Kurset henvender sig til udviklere som vil i gang med at udvikle “Line of Business” applikationer med Microsoft Silverlight 4.

Det bliver fire intensive dage hvor vi kommer rundt om en meget stor del af de features der ligger i Silverlight.

Information og tilmeldning sker her.

Posted in Kursus, Presentations, Silverlight, Talk | Leave a Comment »

Async chain of service calls in Silverlight

Posted by coreclr on November 26, 2009

A colleague of mine asked me how to chain service calls in a Silverlight async model.

Lets say you have these two operations:

string GetId()
void Calculate(string id)

And you must call GetId first and then use the result of that operation to call the Calculate operation.

The solution is pretty simple. We can use our old friend; the AutoResetEvent class. Luckly this exist in Silverlight as well.

First we put the task on the ThreadPool so we don’t block the UI Thread:

private void Button_Click(object sender, RoutedEventArgs e)
{
    ThreadPool.QueueUserWorkItem(StartWork);
}

And here is the StartWork method:

public void StartWork(object state)
{
    var dataService = new DataServiceClient();
    var personService = new PersonServiceClient();

           string id = string.Empty;
           dataService.GetIdCompleted += (s, e) =>
           {
               id = e.Result;

               //signal the event, so the thread can continue
               autoResetEvent.Set();
           };

           //call GetIdAsync
           dataService.GetIdAsync();

           //pause the thread
           autoResetEvent.WaitOne();

           //call CalculateAsync with the id
           personService.CalculateAsync(id);
}

Thats it. Pretty simple.

Posted in .NET, Silverlight, Threading | Leave a Comment »

Silverlight 4 Security Overview White Paper

Posted by coreclr on November 20, 2009

Nick Kramer from Microsoft created a great whitepaper about Silverlight Security. Get it here.

Posted in Silverlight | Leave a Comment »

Silverlight 4 Beta

Posted by coreclr on November 18, 2009

Today we can download a beta version of Silverlight 4.

The tools are here and Expression Blend are here.

Silverlight 4 has a lot of nice features. If you have done any LOB WPF development, you will be very happy to see these new features in Silverlight 4:

– Trusted applications (COM Interop, file-access, network)
– Printing Support
– Right-click context menu
– Clipboard access Support
– Better Data Binding support (grouping/editing, StringFormat)
– Implicit Styling
– RichTextbox support
– IDataErrorInfo support
– Build-in mouse wheel support
– Webcam and microphone support
– Network credentials support (authentication)
– WCF NetTcp Binding
– UDP Multicast Support
– Profiler and Profiler API
– Out of browser Window settings (position, size, chrome)
– Notification windows (toast)
– Embedding HTML (WebBrowser control)
– Same compiled code to be run on the desktop and Silverlight

and off course WCF RIA Services

This page describe all the new features and this page describe known bugs in Silverlight 4.

And finally this page describe a Technical Feature Overview.

Posted in .NET, Silverlight, WPF | Leave a Comment »

RelativeSource Binding in Silverlight 3

Posted by coreclr on November 9, 2009

Silverlight 3 introduced the RelativeSource Binding that we know from WPF.

As the name indicates, RelativeSource  is used when setting up a relative Data Binding.

Lets look at an example. If we want to bind the ToolTip to  Content property on the same element, we can say:

<Button Content="Button" Height="25" Width="75"
    ToolTipService.ToolTip="{Binding Content, 
RelativeSource={RelativeSource Self}}" />

As you can see, when binding to ourself, we don’t need any name on the element.

Another option is to use TemplatedParent.

Lets say that we want to change a Slider template to include a TextBox. And that TextBox should always display the same value as the slider.

Here is the full code:

<Slider Height="84" Margin="229,151,200,0" VerticalAlignment="Top">
    <Slider.Template>
        <ControlTemplate>
            <Grid x:Name="Root">
                <Grid.Resources>
                    <ControlTemplate x:Key="RepeatButtonTemplate">
                        <Grid x:Name="Root" Opacity="0" 
                              Background="Transparent"/>
                    </ControlTemplate>
                </Grid.Resources>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="MouseOver"/>
                        <VisualState x:Name="Disabled"/>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <StackPanel>
                    <Grid x:Name="HorizontalTemplate" 
                          Background="{TemplateBinding Background}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Rectangle x:Name="TrackRectangle" 
                                   Fill="#FFE6EFF7" Stroke="#FFA3AEB9" 
                                   StrokeThickness="{TemplateBinding BorderThickness}" 
                                   RadiusX="1" RadiusY="1" Height="3" Margin="5,0,5,0" 
                                   Grid.Column="0" Grid.ColumnSpan="3"/>
                        <Rectangle x:Name="HorizontalTrackRectangleDisabledOverlay" 
                                   Fill="White" RadiusX="1" RadiusY="1" Height="3" 
                                   Margin="5,0,5,0" Opacity=".55" Visibility="Collapsed" 
                                   Grid.Column="0" Grid.ColumnSpan="3"/>
                        <RepeatButton x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" 
                                      Height="18" IsTabStop="False" Template="{StaticResource 
                            RepeatButtonTemplate}" Grid.Column="0"/>
                        <Thumb x:Name="HorizontalThumb" Height="18" Width="11" IsTabStop="True" 
                               Grid.Column="1"/>
                        <Rectangle x:Name="ThumbDisabledOverlay" Fill="White" RadiusX="2" 
                                   RadiusY="2" Width="11" Opacity=".55" Visibility="Collapsed" 
                                   Grid.Column="1"/>
                        <RepeatButton x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" 
                                      Height="18" IsTabStop="False" 
                                      Template="{StaticResource RepeatButtonTemplate}" 
                                      Grid.Column="2"/>
                    </Grid>
                    <TextBox Width="200" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                        Path=Value}"/>
                </StackPanel>
            </Grid>
        </ControlTemplate>
    </Slider.Template>
</Slider>

The line that we are interested in is this:

<TextBox Width="200"
        Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
        Path=Value}"/>

The TextBox is inside the Slider Template. We use TemplatedParent to bind the Text Property of the TextBox to it’s parent’s Value property (the slider is the parent).

There is a important difference between using a Binding with RelativeSource like this, and using the normal TemplateBinding.

The TemplateBinding is a one-way binding. From the templated parent to a element inside the template. If you need binding both ways, then you should use a Binding with RelativeSource as above.

WPF has two other options that Silverlight don’t: PreviousData and FindAncestor.

With PreviousData we can bind the previous data item in the list of data items being displayed. And FindAncestor refers to the ancestor in the parent chain of the data-bound element

Posted in .NET, Silverlight, WPF | Leave a Comment »