Quantcast
Channel: XAML team's blog
Viewing all 33 articles
Browse latest View live

Adding additional power to RadGridView for Silverlight with attached behaviors

0
0

PART I [example: Adding an ‘Insert new row’ button to RadGridView ]

Certain scenarios require adding additional behaviors and/or visuals to RadGridView. Implementing these as integrated features in RadGridView is not always appropriate as they may serve quite specific client scenarios or may require customization beyond the power of a common integrated feature.

According to the canons of WPF and Silverlight such tasks should be easily achieved by modifying the default control template and adding the necessary visuals (e.g. user controls with some additional logic included).

My experience with clients shows that such approach is sometimes kind-of frustrating as it often involves re-pasting large blocks of obfuscated XAML. I have been often asked if a single-line-of-code approach in certain scenario is possible.

In my following posts I am going to demonstrate how attached behaviors may be useful in cases where RadGridView needs a bit more functionality than provided out-of-the box.

For example – when  building UI to allow user to insert new row the typical approach would be to add a button besides the grid and call RadGridView.BeginInsert() within the button click event  handler.

However many developers prefer to add an ‘Insert new row’ button within the visual structure of the RadGridVIew rather than placing an external button besides.

Something like:

insert_new_screenshot

Adding the button with the add-new-row behavior should be as easy as adding a few lines of XAML:

   1: <telerik:RadGridView x:Name="RadGridView1" >
   2: <i:Interaction.Behaviors>
   3: <behavior:AddNewRowBehavior/>
   4: </i:Interaction.Behaviors>
   5: </telerik:RadGridView>

To have this working you will need to paste the AddNewRowBehavior.cs  to your project as well as a reference to System.Windows.Interactivity assembly. Both you can find in 

.

You may notice that for the purposes of illustration and brevity  I create some buttons in code . If you decide to use this code in your project I would highly recommend to use an user control instead. This will give you an easy way to style it (e.g. colorize or add an image) .

 

In my next post I will demonstrate how to add some client side printing power to RadGridView for Silverlight …


Adding additional power to RadGridView for Silverlight with attached behaviors

0
0

PART II [example: Conditional formatting of cells in RadGridView for WPF and Silverlight]

 

Lets say we have a list of products and we need to mark higher prices (>15.00)  with a red color. Something like :

 

prices_screenshot

 

First lets try it with RadGridView for WPF :

We have to create a small IValueConverter. It will take care to convert the value of the price to the appropriate color:

   1: public class PriceToColorConverter : IValueConverter
   2:     {
   3:         public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   4:         {
   5:             SolidColorBrush brush = new SolidColorBrush();
   6:             decimal price = (decimal) value;
   7:  
   8:             if (price > 15)
   9:                 brush.Color = Colors.Red;
  10:             else
  11:                 brush.Color = Colors.Green;
  12:  
  13:             return brush;
  14:         }
  15:  
  16:         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  17:         {
  18:             throw new NotImplementedException();
  19:         }
  20:     }

 

We use this converter to bind the Foreground property of the cell to the product’s Price :

   1: <Grid>
   2:        <Grid.Resources>
   3:            <local:PriceToColorConverter x:Key="MyConverter" />
   4:        </Grid.Resources>
   5:        <telerik:RadGridView x:Name="RadGridView1" AutoGenerateColumns="False" >
   6:            <telerik:RadGridView.Columns>
   7:                <telerik:GridViewDataColumn DataMemberBinding="{Binding ProductName}" Header="Product" />
   8:                <telerik:GridViewDataColumn DataMemberBinding="{Binding Price}" Header="Price">
   9:                    <telerik:GridViewDataColumn.CellStyle>
  10:                        <Style TargetType="telerik:GridViewCell">
  11:                            <Setter Property="Foreground" Value="{Binding Price, Converter={StaticResource MyConverter}}" />
  12:                        </Style>
  13:                    </telerik:GridViewDataColumn.CellStyle>
  14:                </telerik:GridViewDataColumn>
  15:            </telerik:RadGridView.Columns>
  16:        </telerik:RadGridView>
  17:    </Grid>

And that is all – nice and easy! You may see this in action in 

 

Now lets  try it with RadGridView for Silverlight:

Lets play with the Background property this time.

You know – our RadGridView controls share a common codebase and in most cases code is reusable. Unfortunately not in this case. Silverlight does not support bindings in style setters.

Here is the workaround. We are going to reuse our nice little converter and we need to find it a place. A good place would be the template of the GridViewCell. We are going to modify it , binding the Background with the help of our converter. And here we have to paste the whole 100+  lines of XAML GridViewCell template.

   1: <UserControl x:Class="ConditionalCellFormatting.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   5:     xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"
   6:     xmlns:gridview="clr-namespace:Telerik.Windows.Controls.GridView;assembly=Telerik.Windows.Controls.GridView"
   7:     xmlns:local="clr-namespace:ConditionalCellFormatting"
   8:     mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
   9:     <UserControl.Resources>
  10:         <local:PriceToColorConverter x:Key="MyConverter" />
  11:         
  12:         <SolidColorBrush x:Key="GridLinesFill" Color="#FFB3B3B3"/>
  13:         <SolidColorBrush x:Key="GridViewRowNormalBackground" Color="#FFFFFFFF"/>
  14:         <LinearGradientBrush x:Key="GridViewRowSelectedBackground" EndPoint="0.5,1" StartPoint="0.5,0">
  15:             <GradientStop Color="#FFFFCA5D" Offset="1"/>
  16:             <GradientStop Color="#FFFFDC9C" Offset="0"/>
  17:         </LinearGradientBrush>
  18:         <SolidColorBrush x:Key="GridViewDisabledBackground" Color="#FFEEEEEE"/>
  19:         <SolidColorBrush x:Key="GridViewDisabledBorderBrush" Color="#FFBBBBBB"/>
  20:         <SolidColorBrush x:Key="GridViewDisabledForeground" Color="#FF6F6F6F"/>
  21:         <ControlTemplate x:Key="GridViewCellTemplate" TargetType="gridview:GridViewCell">
  22:             <Grid x:Name="SelectionBackground" Background="{Binding Price, Converter={StaticResource MyConverter}}">
  23:                 <VisualStateManager.VisualStateGroups>
  24:                     <VisualStateGroup x:Name="CommonStates">
  25:                         <VisualState x:Name="Normal"/>
  26:                     </VisualStateGroup>
  27:                     <VisualStateGroup x:Name="EditingStates">
  28:                         <VisualState x:Name="Edited">
  29:                             <Storyboard>
  30:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_EditorPresenter" Storyboard.TargetProperty="Visibility">
  31:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  32:                                 </ObjectAnimationUsingKeyFrames>
  33:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentPresenter" Storyboard.TargetProperty="Visibility">
  34:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Collapsed"/>
  35:                                 </ObjectAnimationUsingKeyFrames>
  36:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="GridViewCellBorder" Storyboard.TargetProperty="Background">
  37:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource GridViewRowNormalBackground}"/>
  38:                                 </ObjectAnimationUsingKeyFrames>
  39:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CurrentBorder" Storyboard.TargetProperty="Visibility">
  40:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  41:                                 </ObjectAnimationUsingKeyFrames>
  42:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CurrentBorder" Storyboard.TargetProperty="Stroke">
  43:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource GridViewRowSelectedBackground}"/>
  44:                                 </ObjectAnimationUsingKeyFrames>
  45:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CurrentBorder" Storyboard.TargetProperty="StrokeThickness">
  46:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="2"/>
  47:                                 </ObjectAnimationUsingKeyFrames>
  48:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CurrentBorder" Storyboard.TargetProperty="StrokeDashArray">
  49:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="0"/>
  50:                                 </ObjectAnimationUsingKeyFrames>
  51:                             </Storyboard>
  52:                         </VisualState>
  53:                         <VisualState x:Name="Display">
  54:                             <Storyboard>
  55:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentPresenter" Storyboard.TargetProperty="Visibility">
  56:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  57:                                 </ObjectAnimationUsingKeyFrames>
  58:                             </Storyboard>
  59:                         </VisualState>
  60:                         <VisualState x:Name="Current">
  61:                             <Storyboard>
  62:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_EditorPresenter" Storyboard.TargetProperty="Visibility">
  63:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Collapsed"/>
  64:                                 </ObjectAnimationUsingKeyFrames>
  65:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentPresenter" Storyboard.TargetProperty="Visibility">
  66:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  67:                                 </ObjectAnimationUsingKeyFrames>
  68:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CurrentBorder" Storyboard.TargetProperty="Visibility">
  69:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  70:                                 </ObjectAnimationUsingKeyFrames>
  71:                             </Storyboard>
  72:                         </VisualState>
  73:                     </VisualStateGroup>
  74:                     <VisualStateGroup x:Name="ValueStates">
  75:                         <VisualState x:Name="Valid">
  76:                             <Storyboard>
  77:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvalidBorder" Storyboard.TargetProperty="Visibility">
  78:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Collapsed"/>
  79:                                 </ObjectAnimationUsingKeyFrames>
  80:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ErrorIcon" Storyboard.TargetProperty="Visibility">
  81:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Collapsed"/>
  82:                                 </ObjectAnimationUsingKeyFrames>
  83:                             </Storyboard>
  84:                         </VisualState>
  85:                         <VisualState x:Name="Invalid">
  86:                             <Storyboard>
  87:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvalidBorder" Storyboard.TargetProperty="Visibility">
  88:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  89:                                 </ObjectAnimationUsingKeyFrames>
  90:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ErrorIcon" Storyboard.TargetProperty="Visibility">
  91:                                     <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible"/>
  92:                                 </ObjectAnimationUsingKeyFrames>
  93:                             </Storyboard>
  94:                         </VisualState>
  95:                     </VisualStateGroup>
  96:                     <VisualStateGroup x:Name="DisabledStates">
  97:                         <VisualState x:Name="Enabled"/>
  98:                         <VisualState x:Name="Disabled">
  99:                             <Storyboard>
 100:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectionBackground" Storyboard.TargetProperty="Background">
 101:                                     <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource GridViewDisabledBackground}"/>
 102:                                 </ObjectAnimationUsingKeyFrames>
 103:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_HorizontalGridLine" Storyboard.TargetProperty="Fill">
 104:                                     <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource GridViewDisabledBorderBrush}"/>
 105:                                 </ObjectAnimationUsingKeyFrames>
 106:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_VerticalGridLine" Storyboard.TargetProperty="Fill">
 107:                                     <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource GridViewDisabledBorderBrush}"/>
 108:                                 </ObjectAnimationUsingKeyFrames>
 109:                                 <ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentPresenter" Storyboard.TargetProperty="Foreground">
 110:                                     <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource GridViewDisabledForeground}"/>
 111:                                 </ObjectAnimationUsingKeyFrames>
 112:                             </Storyboard>
 113:                         </VisualState>
 114:                     </VisualStateGroup>
 115:                 </VisualStateManager.VisualStateGroups>
 116:                 <Border x:Name="GridViewCellBorder" UseLayoutRounding="True" Background="Transparent" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
 117:                 <gridview:AlignmentContentPresenter x:Name="PART_ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Visibility="Visible" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Foreground="{TemplateBinding Foreground}" TextAlignment="{TemplateBinding TextAlignment}" TextDecorations="{TemplateBinding TextDecorations}" TextWrapping="{TemplateBinding TextWrapping}"/>
 118:                 <ContentPresenter x:Name="PART_EditorPresenter" HorizontalAlignment="Stretch" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Visibility="Collapsed"/>
 119:                 <Rectangle x:Name="PART_HorizontalGridLine" Fill="{StaticResource GridLinesFill}" Height="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
 120:                 <Rectangle x:Name="PART_VerticalGridLine" Fill="{StaticResource GridLinesFill}" HorizontalAlignment="Right" VerticalAlignment="Stretch" Width="1"/>
 121:                 <Rectangle x:Name="CurrentBorder" Stroke="#FF000000" StrokeDashArray="1.5" StrokeDashCap="Round" StrokeDashOffset="0" StrokeThickness="1" Height="Auto" Margin="0" Width="Auto" Visibility="Collapsed"/>
 122:                 <Rectangle x:Name="InvalidBorder" Stroke="#FFDB000C" StrokeThickness="2" Height="Auto" Margin="0" Width="Auto" Visibility="Collapsed"/>
 123:                 <Grid x:Name="ErrorIcon" Height="18" HorizontalAlignment="Right" Margin="2,0,2,0" VerticalAlignment="Center" Width="18" Visibility="Collapsed">
 124:                     <Ellipse Fill="#FF535353"/>
 125:                     <Ellipse Fill="#FFCE3527" Stroke="#FFFFFFFF" Margin="1,1,1,1"/>
 126:                     <Path Stretch="Fill" Margin="0.999,1,1.001,8.134" Data="M16,8 C8.127,4.9999293 6.627,10.999763 0,8 0,3.581722 3.581722,0 8,0 12.418278,0 16,3.581722 16,8 z">
 127:                         <Path.Fill>
 128:                             <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
 129:                                 <GradientStop Color="#99FFFFFF" Offset="0"/>
 130:                                 <GradientStop Color="#33FFFFFF" Offset="1"/>
 131:                             </LinearGradientBrush>
 132:                         </Path.Fill>
 133:                     </Path>
 134:                     <Path Stretch="Fill" Stroke="#FF000000" StrokeThickness="2" Margin="5.168,5.748,4.832,4.252" Data="M0.50001547,0.5 L6.5000797,6.5000169 M6.5000155,0.5 L0.5,6.5000704"/>
 135:                     <Path Fill="#FFCE3527" Stretch="Fill" Stroke="#FFFFFFFF" StrokeThickness="2" Margin="5.085,5.084,4.915,4.916" Data="M0.50001547,0.5 L6.5000797,6.5000169 M6.5000155,0.5 L0.5,6.5000704"/>
 136:                 </Grid>
 137:             </Grid>
 138:         </ControlTemplate>
 139:         <Style x:Key="GridViewCellStyle" TargetType="gridview:GridViewCell">
 140:             <Setter Property="Template" Value="{StaticResource GridViewCellTemplate}"/>
 141:             <Setter Property="Padding" Value="3,0,3,0"/>
 142:             <Setter Property="BorderBrush" Value="{StaticResource GridViewRowSelectedBackground}"/>
 143:             <Setter Property="VerticalContentAlignment" Value="Center"/>
 144:             <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
 145:             <Setter Property="Background" Value="Transparent"/>
 146:             <Setter Property="UseLayoutRounding" Value="True"/>
 147:         </Style>
 148:     </UserControl.Resources>
 149:   <Grid x:Name="LayoutRoot">
 150:         <telerik:RadGridView x:Name="RadGridView1" AutoGenerateColumns="False" >
 151:             <telerik:RadGridView.Columns>
 152:                 <telerik:GridViewDataColumn DataMemberBinding="{Binding ProductName}" Header="Product" />
 153:                 <telerik:GridViewDataColumn  CellStyle="{StaticResource GridViewCellStyle}"  DataMemberBinding="{Binding Price}" Header="Price"/>
 154:             </telerik:RadGridView.Columns>
 155:         </telerik:RadGridView>
 156:     </Grid>
 157: </UserControl>

Here is what we have got this time:

 

prices_screenshot_Silverlight

 

For your copy/paste needs , please use

 

Now that is great. What I do not like here actually is that large ugly 5 screens of XAML thing. I may blame the Silverlight platform , I may blame our team for not providing a better way. I will not do that. Instead lets try find a better way via…

Using an attached behavior for conditional formatting in RadGridView for Silverlight

Here is the few-lines-of-code solution :

   1: <telerik:RadGridView x:Name="RadGridView1" AutoGenerateColumns="False" >
   2:             <i:Interaction.Behaviors>
   3:                 <local:ConditionalFormattingBehavior/>
   4:             </i:Interaction.Behaviors>
   5:             <telerik:RadGridView.Columns>
   6:                 <telerik:GridViewDataColumn DataMemberBinding="{Binding ProductName}" Header="Product" />
   7:                 <telerik:GridViewDataColumn DataMemberBinding="{Binding Price}" Header="Price"/>
   8:             </telerik:RadGridView.Columns>
   9:         </telerik:RadGridView>

 

The code of the formatting behavior itself (for brevity - hardcoded for the Price column) :

   1: public class ConditionalFormattingBehavior : Behavior<RadGridView>
   2:     {
   3:         protected override void OnAttached()
   4:         {
   5:             base.OnAttached();
   6:             this.AssociatedObject.RowLoaded += new EventHandler<Telerik.Windows.Controls.GridView.RowLoadedEventArgs>(AssociatedObject_RowLoaded);
   7:         }
   8:  
   9:         void AssociatedObject_RowLoaded(object sender, Telerik.Windows.Controls.GridView.RowLoadedEventArgs e)
  10:         {
  11:             if ((e.Row is GridViewHeaderRow) || (e.Row is GridViewFooterRow) || (e.Row is GridViewNewRow))
  12:                 return; //we want to apply logic to data rows only
  13:  
  14:             Binding colorBinding  = new Binding("Price"){Converter = new PriceToColorConverter()};
  15:             e.Row.Cells[1].SetBinding(GridViewCell.ForegroundProperty, colorBinding);
  16:             //e.Row.Cells[1].SetBinding(GridViewCell.BackgroundProperty, colorBinding);
  17:         }
  18:     }

And of course  a

   using the formatting behavior.

 

We often argue with our front-end developer about which way is better. For him some hundred lines of XAML is nothing to worry about and of course it is the natural Silverlight way of getting the job done. For me it is a silent panic. Now our mission is to give you the choice. You have both in your toolbox now. Drop me a line when you make the decision :) .

Adding additional power to RadGridView for Silverlight with attached behaviors

0
0

PART III [example: Column Groups  A.K.A. Merged Column Headers]

 

Recently we have had a lots of requests for a feature referred as column groups / merged column headers / common headers for two or more columns - something like :

 common_header

Here we have three ordinary columns ( L, W, H)  with regular column headers . There is also an additional common header – ‘Dimensions’ which spans over the three regular headers.

Unfortunately RadGridView for Silverlight and WPF does not support this internally (yet).

 

The good news is that RadGridView is a flexible and easily extendable control so we can easily attach a new column grouping behavior. You can see it in action here:

(live & clickable  example

We set up the common headers codeless  with a few lines of XAML:

   1: <telerik:RadGridView x:Name="RadGridView1" >
   2:             <i:Interaction.Behaviors>
   3:                 <local:ColumnGroupsBehavior>
   4:                     <local:ColumnGroupsBehavior.CommonHeaders>
   5:                         <local:CommonHeader StartColumnIndex="0" Caption="Vehicle Info" ColumnSpan="2" />
   6:                         <local:CommonHeader StartColumnIndex="2" Caption="Dimensions (mm)" ColumnSpan="3" />
   7:                         <local:CommonHeader StartColumnIndex="5" Caption="Total Price" ColumnSpan="1" />
   8:                     </local:ColumnGroupsBehavior.CommonHeaders>
   9:                 </local:ColumnGroupsBehavior>
  10:             </i:Interaction.Behaviors>
  11:         </telerik:RadGridView>

As you can see, when adding a common header we need to set three properties:

StartColumnIndex – defines the first column of the column group

ColumnSpan – tells the header how many columns to unite

Caption – defines the text content of the common header.

 

*We are not limited to text content here. Since the common header is an ordinary user control with its own XAML you can customize it to add any UI elements , images etc.

* This approach has some limitations e.g. column freezing, column reordering  are explicitly disabled by the behavior. We are working on providing this as an internal feature to RadGridView for our  future versions when these limitations will be solved.

 

For your copy/paste needs you can download a 

To have this working in your own project you will have to grab the following :

 

ColumnGroupsBehavior.cs  - the attached behavior itself.

 

CommonHeader.xaml/.cs  - the common header user control. You can modify the XAML within to provide more complex content.

 

SecondaryHeader.xaml/.cs –this is the placeholder for the common headers ( the secondary header row rendered above the ordinary RadGridView header row) . It provides the scrolling & resizing  of the common headers.

 

Additionally you will need a reference to the System.Windows.Interactivity.dll

Displaying images stored in MS SQL with RadGridView for Silverlight

0
0

There are different ways to store images in a SQL database. In our little demo  we have the images placed as binaries in an image type column in a MS SQL table..

As you may know Silverlight works with a limited range of image formats(PNG and JPG). Therefore I have prepared a small sample database with a few jpeg images inside.

 

Silverlight being a client platform does not have direct access to the SQL server. It needs some server-side code to fetch the data. For the purposes of this demo I have used a WCF service  and Linq To Sql to connect to the database and bring our images to the client. You may find the relevant code in the Service1.cs  file in the sample project below. service1

 

RadGridView for Silverlight has some pretty good support for displaying images .The GridViewImageColumn is part of the magic.

 

We can feed the column directly with the raw bytes from the DB (provided they represent a valid PNG or JPG image).

 

<telerik:GridViewImageColumn DataMemberBinding="{Binding Image.Bytes}" ImageWidth="100" />

 

Having the bytes at the client, the above line is all the code we need to have the images displayed.

 

imagesingrid

For your copy/paste needs please use

 

To see it in action you will need the sample database attached to your SQL server and the Connection string in Web.config set to your local server.

Filtering GridViewComboBoxColumn in RadGridView for WPF

0
0

 

GridViewComboBox column is used to display lookup data in user friendly manner. For our demo we bind RadGridView for WPF to a collection of custom Location objects.

 

 

countries_grid

 

As you may notice – each location has a selectable Country field.  Here is the underlying ‘data model’.

 

public class Location
    {
        public int CountryID { get; set; }
        public string CityName { get; set; }
    }
    public class Country
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
 
The location object contains the integer CountryID.Each CountryID corresponds to a certain country and with the help of GridViewComboBoxColumn we see some human readable country names instead of the underlying numeric IDs.
 

Now The Problem :

bad_filter

 

Unfortunately the filter control does not know that our Country IDs are associated with Country objects, so it displays the integer CountryIDs . Of course these numbers mean nothing to the end user. We need to let the user chose from a list of country names instead.

The Solution:  

Being a WPF control RadGridView has great customization abilities. The look and the visual behavior of almost any part of the control may be altered without hurting the functionality. Fortunately this includes the filtering control. As mentioned in Rossen's blog we may easily craft the filtering control  to suite our needs.

 

good_filter

 

I have prepared a simple filtering control (see ComboColumnFilteringControl.xaml) with a ListBox inside to display the human-readable distinct values.

 

Replacing the default filtering control with custom one is easy :

 

<telerik:GridViewComboBoxColumn DataMemberBinding="{Binding CountryID}" Header="Country" DisplayMemberPath="Name" SelectedValueMemberPath="ID"  >
					<telerik:GridViewComboBoxColumn.FilteringControl>
						<local:ComboColumnFilteringControl />
					</telerik:GridViewComboBoxColumn.FilteringControl>
				</telerik:GridViewComboBoxColumn>

 

The rest of the magic is in the ComboColumnFilteringControl.cs - ready to be copy/pasted.

 

The whole sample project may be downloaded from the link:

 

For the purposes of this demo the user control is not exactly visually rich. If you need more complex UI you can easily add any required UI elements into the ComboColumnFilteringControl.xaml.

If you need more complex filtering logic I will recommend to take a look at the following blog , the online example and this help topic.

Math toolbar for column headers in RadGridView for Silverlight

0
0

math_toolbar

 

A client has recently asked for these little fancy math toolbars in the column header. I found it a great idea and thought it might be useful to share the way of implementing this with RadGridView for Silverlight.

 

*Since RadGridView for WPF shares the same code base  the approach bellow may be used for both platforms ( Silverlight and WPF ) .

 

Things are easy with RadGridView !

 

To have this in your project follow these three easy steps :

 

1. Copy the MathToolBar user control from the attached sample project (MathToolBar.xaml, MathToolBar.cs).

2. Replace the default header in the column with the user control.

<telerik:GridViewDataColumn ...
   <telerik:GridViewDataColumn.Header>
     <local:MathToolBar HeaderText="Value1"/>
   </telerik:GridViewDataColumn.Header>
</telerik:GridViewDataColumn>

 

3. Adjust namespaces.

 

Note:

* If  you need different aggregate functions , you may choose from the standard aggregate functions offered by RadGridView,

or you may provide a custom one. Actually the Standard Deviation function in this example is a custom one. More info on how this is implemented may be found in this online example.

 

* if you need to customize the look of the toolbar ( e.g. add/remove buttons, change colors  ), the place to tamper is MathToolBar.xaml.

Cascading ComboBoxes Selection in RadGridView for Silverlight and WPF

0
0

 

A common scenario when entering data is a cascade of comboboxes, where the list in the next combo is populated after selecting a value in the previous.

A typical example is selecting a country from a combo then selecting from a filtered list of cities in a second combo.

We have had tons of questions on how this can be done within a row in RadGridVIew so I decided to make a small demo. I have used a nice List of countries by continent.

 

 

 

cascadingComboboxes

 

 

There are lots of ways to achieve this with RadGirdView. Bellow I have tried to demonstrate the most-descent-in-my-opinion way  :).

As always I should mention that despite the demo uses RadGridVIew for Silverlight the same technique is applicable for RadGridView for WPF as they both share a common API.

 

This time I will dive a bit deeper into the steps required to achieve such behavior. If you just need the sample project please scroll over to the end.

 

1. Bind correctly to data  - the RadGridView and both GridViewComboBoxColumns .

To keep the demo simple I have dumped this  List of countries by continent into the ugly Locations.cs data holder class. (you may download all the files from the link provided at the end)

 

We bind RadGridView to a List of Location objects.

 

public class Location
    {
        public string ContinentCode { get; set; }
        public int? CountryID { get; set; }
        public List<Country> AvailableCountries { get; set; }
    }

*Please note this is a simplified version of the Location class. In the downloadable sample bellow the class implements the INotifyPropertyChanged interface. We need this to ensure immediate updates to the UI when the user makes selection in the combo.

 

Each Location object is associated with a Continent and a Country.

 public class Continent
    {
        public string Code { get; set; }
        public string Name { get; set; }
    }
    public class Country
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string ContinentCode { get; set; }
    }

 

We bind the first combo column to a list of continents, and the RadGridView to a list of locations.

((GridViewComboBoxColumn)this.radGridView.Columns[0]).ItemsSource = Locations.Continents;
this.radGridView.ItemsSource = locations;

 

We bind the second column a bit differently:

(XAML)

<telerik:GridViewComboBoxColumn  ItemsSourceBinding="{Binding AvailableCountries}"

Since the items source will be different for each row – different sets of countries for different continents – we use the ItemsSourceBinding property. The AvailableCountries property of the Location object will hold the filtered by continent countries.

 

 

2. Provide some filtering logic, so that we can have a list of countries for a selected continent.

 

 public IEnumerable<Country> AvailableCountries
        {
            get
            {
                return from c in Locations.Countries
                       where c.ContinentCode == this.ContinentCode
                       select c;
            }
        }

3. Ensure the second column reacts immediately on selection changes in the first combo

The default behavior of RadGridView is to commit the newly selected value after the cell loses focus. In our case we need to update the second column immediately after the selected continent has changed.

 

We subscribe to the RadComboBox.SelectionChangedEvent.

this.AddHandler(RadComboBox.SelectionChangedEvent, new Telerik.Windows.Controls.SelectionChangedEventHandler(comboSelectionChanged));

Within the event handler we update the  underlying business object :

 void comboSelectionChanged(object sender, RadRoutedEventArgs args)
        {
            RadComboBox comboBox = (RadComboBox)args.OriginalSource;
            
            if (comboBox.SelectedValue==null 
                || comboBox.SelectedValuePath != "Code") // we take action only if the continent combo is changed
                return;
            
            Location location = comboBox.DataContext as Location;
            location.ContinentCode = (string) comboBox.SelectedValue;//we submit the value immediately rather than waiting the cell to lose focus.
        }

 

 

Please get all the code as well as a working demo project

Calculated column in RadGridView for Silverlight + math expressions

0
0

When the data layer does not allow to perform calculations we often need to harness the UI.

Here is a a simple case  - in our business object we have the Price and the Count properties. We will have RadGridView to calculate the Total  for us in a calculated column.

 

calculated_column

 

If you peek into the sample project you will notice we are using a pretty standard Silverlight approach :

We bind the value of the calculated column with a Binding Converter :

<telerik:GridViewDataColumn 
					Header="Total" 
					Background="Bisque" 
					DataMemberBinding="{Binding Converter={StaticResource CalculatingConverter}}" 
					TextAlignment="Right" />
 
The calculation “logic” is in the Convert method of CalculatingConverter.cs
 
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return ((Item)value).Price * ((Item)value).Count;
        }
 
For simple scenarios it should do the trick . The bad thing is we have hardcoded the converter to our Item class with Price and Count properties.
What if we need a more dynamic approach  - to give the RadGridView a string Expression like “Price*Count  and have it evaluate and calculate for us. 
 
The Poor Man’s Expression Parser
 
A popular hack when a simple expression parser is needed in Silverlight is to call the javascript eval function from the hosting browser window. 
Here is how our “dynamic expression” converter will look like : 
public class CalculatingConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string stringexpression = BuildExpression(value, parameter.ToString());
            return HtmlPage.Window.Invoke("eval", stringexpression);
        }
        private string BuildExpression(object value, string parameter)
        {
            StringBuilder sb = new StringBuilder(parameter);
            foreach (PropertyInfo propertyInfo in value.GetType().GetProperties())
            {
                if (propertyInfo.CanRead)
                {
                    object o = propertyInfo.GetValue(value, null);
                    sb.Replace(propertyInfo.Name, o.ToString());
                }
            } 
            return sb.ToString();
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
 
This gives us the power to pass the column a string expression - ‘Price*Count’ ( as a parameter of the value converter ): 
 
DataMemberBinding="{Binding Converter={StaticResource CalculatingConverter},ConverterParameter='Price*Count'}" 
 
For your copy/paste needs please download the 

 

[UPDATE]

If we move the calculation logic where it belongs  - the data layer, we may benefit from the INotifyPropertyChanged interface. This way the user will be able to change values in cells and get the totals recalculated in a spreadsheet alike manner. This approach is demonstrated in

 

 

.


Empty data template in RadGridView for Silverlight (and WPF)

0
0

 

One more RadGridView behavior frequently requested by our clients is to display a message when there are no records to display. A typical real life scenario would be a RadGridView displaying a list of search results. When there are no results found we would like to have a message like “No results found!” displayed in RadGridView.

 

noresults

 

 

If you download the project above , you will see that if you get the EmptyDataTemplateBehavior.cs into your project, setting the empty data template will be as easy as writing a few lines of XAML :

<telerik:RadGridView x:Name="RadGridView1" >
			<i:Interaction.Behaviors>
				<local:EmptyDataTemplateBehavior>
					<local:EmptyDataTemplateBehavior.EmptyDataTemplate>
						<DataTemplate>
							<TextBlock Text="No results found!" Foreground="White"  HorizontalAlignment="Center"  VerticalAlignment="Center" Visibility="{Binding MessageVisibility}" />
						</DataTemplate>
					</local:EmptyDataTemplateBehavior.EmptyDataTemplate>
				</local:EmptyDataTemplateBehavior>
			</i:Interaction.Behaviors>
		</telerik:RadGridView>

 

*As you may know from my previous posts concerning attached behaviors , you will need  to add a reference to the System.Windows.Interactivity.dll.

*As always the same approach is applicable for the WPF version of RadGridView provided that you reference the right version of the System.Windows.Interactivity.dll.

Restyling RadDataPager for WPF and Silverlight

0
0

 

A small but powerful control has joined the great family of Telerik XAML controls with the recent release.
RadDataPager is a result of an increasing demand from our customers who needed to work with large amounts of server data presented in small portions at the client side. 
The primary goal was to make a powerful data paging control to be used in any scenarios requiring getting and presenting portions of data.
How good is RadDataPager in working with paged data you can see in Rossen's announcement.

Yet being a XAML control it challenged us with making one more visually appealing and highly customizable control.

It offers a slick look in all available WPF/Silverlight Telerik themes:

 

RadDataPager-Themes 

As you can see the default design is targeting mainly business scenarios.

At the same time being an example for a truly lookless XAML control RadDataPager allows restyling with minimal efforts this way widening the possible range of applications.  Lets see what we can doo with a few lines of XAML :

<Style x:Key="buttonStyle" TargetType="ButtonBase" >
				<Setter Property="Template">
					<Setter.Value>
						<ControlTemplate TargetType="ButtonBase">
							<Grid  Width="40" Background="Black">
								<Ellipse StrokeThickness="2" VerticalAlignment="Center" Width="15" Height="15" HorizontalAlignment="Center" Fill="Gray" />
								<Ellipse Visibility="{Binding IsCurrent, Converter={StaticResource VisibilityConverter}}" VerticalAlignment="Center" Height="16"  Fill="White" HorizontalAlignment="Center"  Width="16"/>
							</Grid>
						</ControlTemplate>
					</Setter.Value>
				</Setter>
			</Style>
			...
			<telerik:RadDataPager NumericButtonStyle="{StaticResource buttonStyle}" ...
And the result:
pager_IPhoneStyle

The IPhone-style-thing bellow the RadCoverFlow is actually our RadDataPager.

      

With a few more lines of XAML we may get  almost any imaginable look of the pager control including the fascinating result demonstrated in the short video on the top.

Some fun with RadGridView for Silverlight …literally !

0
0

April Fools' Day is a great excuse for me to do something funny with RadGridView. So today’s post will have less geekness and more fun than usually.

 

Silverlight being a great platform and RadGridView being enormously flexible control provoked me to do something that you can not exactly call the typical Line-Off-Business application.

 

So enjoy this small  Pexeso game clone created with the help of RadGridView for Silverlight and some standard Silverlight re-styling techniques.

The rules are simple : Try to open two identical cards at the same time. The goal of the game – try to open all cards this way.

My best score was 3:43 !  Will be glad if you share yours :) .

 

For the sake of geekness I will keep the tradition to share the sources.

Those of you who need an example of altering the behavior of the cells in RadGridView by using the CellTemplate property and a custom user control,

please download the following sample project :

 

download link : \RadGridViewPexeso.zip

Displaying live streaming data with RadGridView for Silverlight and WPF

0
0

Animated cells on value changes

 

When dealing with streaming data which is updated over time the end user should be able to quickly track changes at a glance. A typical application that would benefit from this would be a financial dashboard, live data monitoring and tracking systems etc. For the purpose of illustration I have prepared a small simulation of streaming financial data (stock prices) .

  Get Microsoft Silverlight  

In my previous blogpost I have already demonstrated how we can alter/extend the behavior of cells in RadGridView by placing a user control inside. This blog post demonstrates a more real-life and business oriented scenario.
All the animation and image selection logic is capsulated in the StockPricePresenter user control. Placing this control inside the cell is a standard routine:
  <Grid.Resources>
            <DataTemplate x:Key="StockPriceTemplate">
                <local:StockPricePresenter StockPrice="{Binding StockPrice}" OldStockPrice="{Binding OldStockPrice}" />
            </DataTemplate>
        </Grid.Resources>
        <telerik:RadGridView x:Name="gridViewStockPrices" IsFilteringAllowed="False" ShowGroupPanel="False" Width="350" AutoGenerateColumns="False" >
            <telerik:RadGridView.Columns>
...
...
...
                <telerik:GridViewDataColumn Width="*" CellTemplate="{StaticResource StockPriceTemplate}" DataMemberBinding="{Binding StockPrice}" DataFormatString="{}{0:C}" />
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>

Using the CellTemplate property we can tweak the cell appearance and behavior according to our requirements.

For your copy/paste needs please download the full source code here:

(Silverlight 4 VS2010) download

UPDATE :

Frozen / Pinned rows in RadGridView for Silverlight

0
0

A common UX pattern when working with large tabular data is the so called frozen rows or pinned rows. This is very popular in the spreadsheet world and in some text editors as well.

 

 frozen_spreadsheet

I have tried to resemble this behavior with RadGridView for Silverlight. The user may pin a row thus preventing it from vertical scrolling. This way important items may be kept inside the viewport regardless the position of the vertical scrollbar. Pinned items remain on top for easy access.

frozen rows

 

Adding this behavior to RadGridView is simple and painless:

        <telerik:RadGridView x:Name="RadGridView1" >
            <i:Interaction.Behaviors>
                <local:FrozenRowsBehavior/>
            </i:Interaction.Behaviors>
        </telerik:RadGridView>

 

These lines should be all the XAML needed to enable it. The pin button is located in  PinButton.xaml and PinButton.cs.The behavior itself can be found in FrozenRowsBehavior.cs

You will also need a reference to the System.Windows.Interactivity.dll.

The following demo application demonstrates this in action. To freeze/unfreeze a row just click on the pin icon on the right. When you have a few frozen rows you may play with the vertical scrollbar to test the behavior.

 

 

The whole demo application can be downloaded

New control for WPF and Silverlight from Telerik - RadDataForm

0
0

In the context of our 30th release I am happy to share even more good news with you. With the official Q1 2011 release we have enriched the developer toolbox with the new RadDataForm.In the tradition of our existing data-aware controls such as RadGridVIew, RadDataForm deals with data in easy and intuitive  way. It provides complete CRUD support over an object or a collection of objects taking care of adding, editing, deleting and navigation trough collections. We had the RadGridView to take care of tabular views and now we have RadDataForm to take care of scenarios where form layout is more suitable. RadDataForm shares a common data engine with the rest of our data-aware controls thus providing flexibility and scalability.

From the very first moment after the release I keep getting the question – Where is the RIA services example with RadDataForm .  So with the help of the RadDomainDataSource, the BusinessApplication template in VS2010 and the good old NorthWind database I gathered a small sample app for you.

 

RadDataForm, RadDomainDataSource and RIA Services how to :

 

1. Create a standard Business Application following e.g. the steps described here. We use the customers table with editing enabled.

 

2. Add references to the following assemblies :

refs

 

3.Place RadDataForm and RadDomainDataSource  in XAML the following way :

 <Grid x:Name="LayoutRoot">
        <telerik:RadDomainDataSource x:Name="customersDataSource" 
                                     AutoLoad="True" 
                                     QueryName="GetCustomers" 
                                     >
            <telerik:RadDomainDataSource.DomainContext>
                <svc:NorthWindDomainContext />
            </telerik:RadDomainDataSource.DomainContext>
        </telerik:RadDomainDataSource>

        <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
            
            <telerik:RadDataForm Header="Customers"
                          AutoGeneratingField="RadDataForm_AutoGeneratingField"
                          CommandButtonsVisibility="Cancel,Commit,Edit,Navigation" 
                          EditEnded="RadDataForm_EditEnded"
                          ItemsSource="{Binding DataView, ElementName=customersDataSource}" />
        </StackPanel>
    </Grid>

 

4. Some code to allow submitting data to the server:

private void RadDataForm_EditEnded(object sender, EditEndedEventArgs e)
        {
            this.customersDataSource.SubmitChanges();
        }
 
And that is all ! We have a fully functional CRUD enabled application.
 
 df_demo_1 
 
 
 

RadDataForm and RadGridView integration - popup editing.

0
0

 

Often collection data is better presented in a tabular view and better edited in a form view. Such UX approach is referred by our clients as “Popup editing in RadGridView”.

With the help of the new RadDataForm and the good old RadGridView a few lines of code are needed to accomplish this.

popupEditingInRadGridView

To have this working we need to :

1. Bind RadGridView to a collection IEditable and INotifyPropertyChange objects.

this.RadGridView1.ItemsSource = Person.GetSampleListOfPersons();

2. Bind a RadDataForm  to the current item of RadGridView

 

 <telerik:RadDataForm CurrentItem="{Binding CurrentItem,ElementName=RadGridView1}" …
 

3. Handle  the button event to show RadDataForm when needed.

 

private void Edit_Click(object sender, RoutedEventArgs e)
        {
            this.RadGridView1.CurrentItem = ((Button)sender).DataContext;
            this.RadDataForm1.Visibility = Visibility.Visible;
            this.RadDataForm1.BeginEdit();
        }


4.Handle the EditEnded event of RadDataform to hide it when no more needed.

 

void RadDataForm1_EditEnded(object sender, Telerik.Windows.Controls.Data.DataForm.EditEndedEventArgs e)
    {
        this.RadDataForm1.Visibility = Visibility.Collapsed;
    }
 

That is all you need to have  popup editing in RadGridView .

 

The full source code and a demo app  may be downloaded


Creating custom drag arrow in Silverlight

0
0

Since Q3 2011 we have changed the default drag API used. It allows creating more complex scenario as well as building MVVM friendly drag behaviors. However, it does not support drag arrow which, although not very popular feature is still used. Thus, when arrow was required, we have suggesting using legacy execution mechanism.

In this blog I will write how to create your own drag arrow using DragDropManager events. So, basically we will use AddDragInitialize, GiveFeedback and DragDropCompleted to create and control the arrow. We also use Popup to display it on the screen.

The arrow itself is located in Arrow class which derives from Content control and has its own template defined. Thus you can create custom arrow by simply adding new style to this control.

 

So, in order to use it you can just add the following lines in your code:

- Initialize ArrowService:

private void Application_Startup(object sender, StartupEventArgs e) 

{ 
     this.RootVisual = new MainPage();
     ArrowService.Initialize(this.RootVisual);
} 
- Enable Arrow on drag:
ArrowService.DisplayDragArrow = true;
 

That way you have full control of arrow appearance and behavior. I hope you’ll like it.

Download Silverlight project

Telerik XAML controls Q1 2012 are here

0
0

The latest Q1 2012 versions of RadControls for Silverlight and RadControls for WPF are available for download under the users’ accounts: 

RadControls for Siverlight Download

RadControls for WPF Download

You can check the release notes and the latest demos at:

RadControls for Silverlight Demos | Release Notes

RadControls for WPF Demos | Release Notes

There are 5 brand new controls that we included in this release:

Diagrams Beta


GanttView CTP


TimeLine


ListBox Beta


DataBar


As always we will greatly appreciate your feedback in our forums and support system.

Cheers,

The XAML Team




Telerik Welcomes Jesse Liberty

0
0

Today we are thrilled to welcome industry veteran Jesse Liberty to Telerik as our new XAML Evangelist.  Many of you know him as the host of Yet Another Podcast and author of Programming C#, Programming Reactive Extensions and LINQ, and Migrating to Windows Phone.  His experience spans a variety of roles, including Software Architect for PBS, Vice President of Information Technology at Citibank, and, most recently, Developer Community Evangelist for the Microsoft Windows Phone Team.

As we continue to improve our XAML suites, our initiatives in the Windows 8 space will also continue to develop.  Jesse joins fellow Telerik XAML Evangelists, Evan Hutnick and Michael Crump, in delivering the latest and greatest content and guidance for Silverlight, WPF, Windows Phone, and, increasingly, Windows 8.  Telerik continues its dedication to offering the best software development products for all platforms (check out Telerik's Platform Guidance!), from the most mature to the most cutting-edge, and Jesse’s experience and enthusiasm for XAML will be an invaluable addition toward that effort.

You’ll soon be hearing from him on our XAML Team blogs as well as our ongoing XAMLflix blog series.  And that’s just to start!  So get psyched and stay tuned as 2012 promises breakthrough developments and significant enhancements to all things Telerik XAML.

Jesse’s thoughts about his new role can be read on his blog.


Cheers,

The XAML Team

Introducing PDF Viewer for Silverlight/WPF

0
0

The long-awaited 2012 Q1 with the first official version of RadPdfViewer is already a fact! This is also the first release of the control for WPF, so don’t forget to check it out in the demos if you have missed it: WPF and Silverlight.

A big “Thank You” to all who tried using RadPdfViewer for Silverlight when it was still in a beta stage for providing such a valuable feedback on the control! We have come a long way with your help and hope that you will enjoy the improvements that the first official version brings out.


For the past few months after we first introduced RadPdfViewer as Beta, we have managed to extend the list of supported PDF features in order to be able to show correctly intrinsic PDF files like the ones normally used in LOB applications. The ameliorations include a wider set of image formats and an extensible architecture for plugging in custom filters. The text rendering system was also rethought and improved to ensure the professional look of the document preview. We also managed to implement clipping and support for color spaces, further polishing the way PDF files are shown. Last but not least, if you use the control in Silverlight 5, you will now be able to print your documents faster and with less memory footprint, because the control now utilizes the vector printing of Silverlight 5.

In the 2012 Q1 release an MVVM friendly API is introduced, which will help you integrate RadPdfViewer more easily. Following popular demand, the DocumentSource of RadPdfViewer has been implemented as a DependencyProperty, allowing data-binding to a Stream, a URI where a document can be found, or a string representing such a URI. For example, if Source is the property in your view-model which you wish to bind the content of the viewer to, you can do that as follows:

<telerik:RadPdfViewer x:Name="viewer" DocumentSource="{Binding Source, Converter={StaticResource PdfDocumentSourceValueConverter}}" />

PdfDocumentSourceValueConverter is a static resource declared as:

<fixed:PdfDocumentSourceValueConverter x:Key="PdfDocumentSourceValueConverter" />

The toolbar that RadPdfViewer used in the beta has been implemented as a separate control now in order to allow customizations of the functionality provided to the end user.

Here is an example of how a RadToolBar can be wired with the commands of the PdfViewer:

  <telerik:RadToolBar DataContext="{Binding ElementName=pdfViewer, Path=Commands}">

            …

  </telerik:RadToolBar>

After setting the DataContext of the toolbar, you can proceed to fill in buttons bound to the commands of the viewer like this:

            <controls:RadButton Padding="4" Command="{Binding OpenPdfDocumentCommand}">

                <ToolTipService.ToolTip>

                    <TextBlock Text="Open" />

                </ToolTipService.ToolTip>

                <Image Source="/Telerik.Windows.Controls.FixedDocumentViewers;component/Images/open.png" Stretch="None" />

            </controls:RadButton>

In this way, you will get the same button that the navigation panel of RadPdfViewer had in the beta version. Only that this time, you can customize the tooltip and the icon or even change the command executed. If you would like to preserve the look of the PdfViewer from the Beta, you can open the demos and copy the content from there. Of course, you can implement other kind of UI just as easily.

Now the experience you get with RadPdfViewer for Silverlight will be much closer to the desktop applications you use for viewing PDFs. What is more, you can build applications with similar look and functionality for Silverlight and WPF with minimal effort.

Happy developing! 

What's New in the RichTextBox for Silverlight/WPF?

0
0

The first release of 2012 is already a fact and even though this Q has been shorter due to the shift in the release dates which Todd Anglin blogged about, we managed to include some long-awaited improvements and new features.

The first and most important change is that RadRichTextBox now supports multiple sections in the document. To see how it works, you can open the Silverlight demo, choose the Page Layout tab from the RibbonUI and click “Breaks”.


Inserting a section break will split the current section into two, providing the option to format the two parts differently. Section breaks are extremely useful when you want to have different layout of pages in the document – margins and/or orientation. Furthermore, each section can have a different set of headers and footers, which in addition to the customizations within one section – Default header/footer, Even and Odd page, lays the foundations for the creation of more complex and sophisticated documents.

You can also specify whether the next section should start with an even or odd page similarly to how this can be done in Microsoft Word. The section breaks and the headers/footers will be imported and exported in most formats – XAML, docx, RTF and PDF (export only).

Another major feature we have been working on over the last two releases is Styles support. The usage of styles allows easier formatting of the document while at the same time preserving the consistent look of the document. Styles can be created and added to a document programmatically or via the ManageStylesDialog.

The supported styles are for paragraph, character and table. Last but not least, styles are persisted in docx, XAML and HTML, so they can also be instantiated on import.

In 2012 Q1 we have done our best to make data binding easier, to better enable scenarios like MVVM. Previously, to bind RadRichTextBox, you had to introduce a new object to the visual tree - a data provider - and bind it to the editor. In the new release, we have removed a lot of that complexity altogether and now you only need to bind an attached property (on the editor) to your desired data source. Here's an example:

<telerik:RadRichTextBox html:HtmlDataProvider.Source="{Binding MyModelProperty}" />

This example utilizes HtmlDataProvider, but you can use any other in its place, depending on the needs of your application.

Also, due to popular demand, we have introduced a DocxDataProvider, so now you can also bind your byte[] properties the same way you do with the string ones. It too features the Source attached property as shown above.

Stay tuned for more interesting news around RadRichTextBox. Your feedback, as always, will be much appreciated.

Viewing all 33 articles
Browse latest View live




Latest Images