ItemsPanelTemplate Differences in SL and WPF

I was changing the ItemsPanelTemplate of Listbox and set the Position of Elements generated using TranslateTransform

WPF app works fine, while the Silverlight app crashes. As far as I can tell the code is same

Here is the XAML
<UserControl x:Class=”t14.Page”
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
    Width=”400″ Height=”300″>
    <UserControl.Resources>
        <DataTemplate x:Key=”dt”>
            <TextBlock Text=”{Binding Name}”>
                <TextBlock.RenderTransform>
                    <TranslateTransform X=”{Binding Position.X}”
                                        Y=”{Binding Position.Y}” />
                </TextBlock.RenderTransform>
            </TextBlock>
        </DataTemplate>
    </UserControl.Resources>
    <Canvas x:Name=”c1″>
        <ListBox x:Name=”list1″ ItemTemplate=”{StaticResource dt}” >
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Width=”500″ Background=”Azure”
                            Height=”500″></Canvas>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
    </Canvas>
</UserControl>

and code behind

public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            List<Customer> customers = new List<Customer>();
            customers.Add(new Customer { Name = “Customer..1”, Position = new Point {X=100,Y=100 } });
            customers.Add(new Customer { Name = “Customer..2”, Position = new Point { X = 50, Y = 50 } });
            customers.Add(new Customer { Name = “Customer..3”, Position = new Point { X = 150, Y = 150 } });
            customers.Add(new Customer { Name = “Customer..4″, Position = new Point { X = 200, Y = 200 } });
            list1.ItemsSource = customers;
        }

      
    }

    public class Customer
    {
        public Point Position { get; set; }
        public string Name { get; set; }
    }

I also tried to set ItemContainerStyle like this in SL, but it crashes

  <Style x:Key=”st1″
               TargetType=”ListBoxItem”>
            <Setter Property=”Canvas.Left”
                    Value=”{Binding Position.X}” />
            <Setter Property=”Canvas.Top”
                    Value=”{Binding Position.X}” />
        </Style>

I set same thing in WPF, it works

 <Style x:Key=”st1″ TargetType=”{x:Type ListBoxItem}”>
            <Setter Property=”Canvas.Left”
                    Value=”{Binding Position.X}” />
            <Setter Property=”Canvas.Top”
                    Value=”{Binding Position.X}” />
        </Style>
you can download the sample app here

Advertisements

Customizing TabItem Style(no coding)

Wanted to take a shot at customizing the appearance of TabItem in TabControl.

TabControl itself has few issues, we dont want to go there and will foucs on styling TabItem

I have included the style I picked up from generic.xaml in the source

The Template (removed resources, VSM related stuff) looks like this

<Grid x:Name=”Root”>                  
          <Border x:Name=”TabBorder”
                  BorderBrush=”Black”
                  BorderThickness=”1″
                  CornerRadius=”2,2,0,0″
                  Background=”{TemplateBinding Background}”>
            <Border.RenderTransform>
              <TranslateTransform Y=”0″
                                  X=”0″/>
            </Border.RenderTransform>
            <Border BorderThickness=”1″
                    BorderBrush=”{StaticResource AccentBrush}”>
              <Border.Background>
                <LinearGradientBrush StartPoint=”0.7,0″
                                     EndPoint=”0.7,1″>
                  <GradientStop x:Name=”LinearBevelLightStart”
                                Color=”{StaticResource LinearBevelLightStartColor}”
                                Offset=”0″ />
                  <GradientStop x:Name=”LinearBevelLightEnd”
                                Color=”{StaticResource LinearBevelLightEndColor}”
                                Offset=”0.35″ />
                  <GradientStop x:Name=”LinearBevelDarkStart”
                                Color=”{StaticResource LinearBevelDarkStartColor}”
                                Offset=”0.35″ />
                  <GradientStop x:Name=”LinearBevelDarkEnd”
                                Color=”{StaticResource LinearBevelDarkEndColor}”
                                Offset=”1″ />
                </LinearGradientBrush>
              </Border.Background>
              <Grid>
                <Rectangle x:Name=”SelectedBackground”
                           Fill=”#FFFFFFFF”
                           Opacity=”0″
                           Margin=”0,0,0,-2″ />
                <ContentControl
                  Grid.RowSpan=”2″
                  x:Name=”Header”
                  Content=”{TemplateBinding Header}”
                  Foreground=”{TemplateBinding Foreground}”
                  FontSize=”{TemplateBinding FontSize}”
                  FontFamily=”{TemplateBinding FontFamily}”
                  HorizontalAlignment=”{TemplateBinding HorizontalAlignment}”
                  VerticalAlignment=”{TemplateBinding VerticalAlignment}”
                  Margin=”6,2,6,1″ />
              </Grid>
            </Border>
          </Border>

I wanted to make it something different (nothing exciting, just different), I ended up with this for the template

tab2 – disabled, tab4 – active(selected)

<Grid x:Name=”Root”>
  <Border CornerRadius=”8,2,0,0″
          BorderBrush=”Black”
          BorderThickness=”1,1,1,0″>
    <ContentControl Grid.RowSpan=”2″
                    x:Name=”Header”
                    Content=”{TemplateBinding Header}”
                    Foreground=”{TemplateBinding Foreground}”
                    FontSize=”{TemplateBinding FontSize}”
                    FontFamily=”{TemplateBinding FontFamily}”
                    HorizontalAlignment=”{TemplateBinding HorizontalAlignment}”
                    VerticalAlignment=”{TemplateBinding VerticalAlignment}”
                    Margin=”6,5,6,5″ />
  </Border>
  <Rectangle Height=”2″
             Margin=”8,4,4,4″
             Opacity=”0″
             x:Name=”rect1″
             VerticalAlignment=”Top”>
    <Rectangle.Fill>
      <SolidColorBrush Color=”orange”
                       x:Name=”RectangleColor”></SolidColorBrush>
    </Rectangle.Fill>
  </Rectangle>
</Grid>

Basically it just has a border, contentcontrol and rectangle.

that alone will work, but we do want some visualstates, unselected, selected, mouseover, normal, disabled
all we are going to do is make the rectangle visible, change colors, change opacity based on the states

so keeping the VisualState names same as before, I ended up with this for VSM

<vsm:VisualStateManager.VisualStateGroups>
  <vsm:VisualStateGroup x:Name=”CommonStates”>
    <vsm:VisualStateGroup.Transitions>
      <vsm:VisualTransition Duration=”0″ />
      <vsm:VisualTransition To=”MouseOver”
                            Duration=”0:0:0.1″ />
    </vsm:VisualStateGroup.Transitions>
    <vsm:VisualState x:Name=”Normal” />
    <vsm:VisualState x:Name=”MouseOver”>
      <Storyboard>
        <DoubleAnimation Storyboard.TargetName=”rect1″
                         Storyboard.TargetProperty=”Opacity”
                         To=”1″
                         Duration=”0″ />
      </Storyboard>
    </vsm:VisualState>
    <vsm:VisualState x:Name=”Disabled”>
      <Storyboard>
        <DoubleAnimation Storyboard.TargetName=”Root”
                         Storyboard.TargetProperty=”Opacity”
                         To=”0.5″
                         Duration=”0″ />
      </Storyboard>
    </vsm:VisualState>
  </vsm:VisualStateGroup>
  <vsm:VisualStateGroup x:Name=”SelectionStates”>
    <vsm:VisualState x:Name=”Unselected”>
      <DoubleAnimationUsingKeyFrames Storyboard.TargetName=”Root”
                                     Storyboard.TargetProperty=”(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)”
                                     BeginTime=”00:00:00″
                                     Duration=”00:00:00.0010000″>
        <SplineDoubleKeyFrame KeyTime=”00:00:00″
                              Value=”5″ />
      </DoubleAnimationUsingKeyFrames>
    </vsm:VisualState>
    <vsm:VisualState x:Name=”Selected”>
      <Storyboard>
        <DoubleAnimation Storyboard.TargetName=”rect1″
                         Storyboard.TargetProperty=”Opacity”
                         To=”1″
                         Duration=”0″ />
        <Storyboard>
          <ColorAnimation Storyboard.TargetName=”RectangleColor”
                          Storyboard.TargetProperty=”Color”
                          To=”green”
                          Duration=”0″ />
        </Storyboard>
      </Storyboard>
    </vsm:VisualState>
  </vsm:VisualStateGroup>

and used the style like this

<my:TabControl>
  <my:TabItem Style=”{StaticResource st1}”
              Header=”tab1″ >
    <TextBlock Text=”Some Content in tab1″></TextBlock>
  </my:TabItem>
  <my:TabItem Style=”{StaticResource st1}”
              IsEnabled=”False”
              Header=”tab2″>
    <TextBlock Text=”Some Content in tab2″></TextBlock>
  </my:TabItem>
  <my:TabItem Header=”tab3″
              Style=”{StaticResource st1}”>
    <TextBlock Text=”Some Content in tab3″></TextBlock>
  </my:TabItem>
  <my:TabItem Header=”tab4″
              Style=”{StaticResource st1}”>
    <TextBlock Text=”Some Content in tab4″></TextBlock>
  </my:TabItem>
</my:TabControl>

you can download the source here

Drag & Drop DataGridRows

Here is the sample code for drag & drop of the DataGridRows I did couple of months back updated to work in beta 2

We dont get mouse events so we have to use another canvas or something which will sit on top of the datagrid at the same location as the datagird, we set the zIndex to a higher number

   <Canvas Width=”300″ x:Name=”datagrid1Canvas”
 Canvas.ZIndex=”2″
        Margin=”80,85,0,10″
        Height=”250″
        Background=”Transparent”/>

you can download the source here

Showing and Hiding Datagrid Columns

if we want to show and hide DataGrid columns in Silverlight Beta2, we will run into issues if we use Visibility.Collapsed and Visibility.Visible
the following seems to work
we have to set MinColumnWidth property to 0

//grid1 name of the grid
grid1.MinColumnWidth = 0;

//hide the column
grid1.Columns[0].Width = new DataGridLength(0);

//show the column
grid1.Columns[0].Width = DataGridLength.Auto;

you can download source here

Working with VisualStateManager

VisualStateManager seems to be a nice addition and it seem to work :).Creating the animations and the creation of different states and the animations is very intutive and easy 

 created a quick app in VS which basically is a listbox binding to some customers and a UserControl shows the selected Customer Details. I wanted to see if I can change some Colors/Properties in the UserControl when the SelectedItem changes in the listbox so Added a VisualStateGroup in Blend called ‘MyStateGroup’ and added Transitions, which basically change Background Foreground Colors

<vsm:VisualStateManager.VisualStateGroups>
 <vsm:VisualStateGroup x:Name=”MyStateGroup”>
    <vsm:VisualStateGroup.Transitions>
        <vsm:VisualTransition Duration=”00:00:01″
                              To=”Customer1″ />
        <vsm:VisualTransition Duration=”00:00:01″
                              To=”Customer2″ />
        <vsm:VisualTransition Duration=”00:00:01″
                              To=”Customer3″ />
        <vsm:VisualTransition Duration=”00:00:01″
                              To=”AllOthers” />
    </vsm:VisualStateGroup.Transitions>
    <vsm:VisualState x:Name=”Customer1″>
        <Storyboard>
            <ColorAnimationUsingKeyFrames BeginTime=”00:00:00″
                                          Duration=”00:00:00.0010000″
                                          Storyboard.TargetName=”LayoutRoot”
                                          Storyboard.TargetProperty=”(Panel.Background).(SolidColorBrush.Color)”>
                <SplineColorKeyFrame KeyTime=”00:00:00″
                                     Value=”#FF988787″ />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </vsm:VisualState>
    <vsm:VisualState x:Name=”Customer2″>
        <Storyboard>
            <ColorAnimationUsingKeyFrames BeginTime=”00:00:00″
                                          Duration=”00:00:00.0010000″
                                          Storyboard.TargetName=”LayoutRoot”
                                          Storyboard.TargetProperty=”(Panel.Background).(SolidColorBrush.Color)”>
                <SplineColorKeyFrame KeyTime=”00:00:00″
                                     Value=”#FFA82727″ />
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </vsm:VisualState>
    …
    <vsm:VisualState x:Name=”AllOthers”>
        <Storyboard />
    </vsm:VisualState>
  </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>

When the selction changes in the listbox, GoToState Method is called with the control, Name of the VisualState to go to and true as parameters. VisualStates are defined only for the first 3 items, when they are selected we can see the effects.
if we pass false we don’t get any transition effects and the change will be instant.

It would have been nice if we have a list of Transitions to pick from

private void list1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        Customer c = list1.SelectedItem as Customer;
        uc1.DataContext = c;
        if (c.FirstName.Contains(“1”))
            VisualStateManager.GoToState(uc1, “Customer1”, true);
        else if (c.FirstName.Contains(“2”))
            VisualStateManager.GoToState(uc1, “Customer2”, true);
        else if (c.FirstName.Contains(“3”))
            VisualStateManager.GoToState(uc1, “Customer3”, true);
        else
            VisualStateManager.GoToState(uc1, “AllOthers”, true);
    }

you can download the source here