Header Color bound to Selection State

9 posts, 4 answers
  1. Ronald Bouras
    Ronald Bouras avatar
    11 posts
    Member since:
    Jun 2010

    Posted 14 Dec 2010 Link to this post

    Hi everybody,

    here´s the scenario:
    We want to enable our applications users to select some of the tiles shown in a TileView control (for example to send a letter to some of the shown persons etc.). To indicate each tile´s selection state of course we want to switch the color of the tile´s header ;-)

    We were basically able to modify the template of the RadTileViewItem and there changing the header color IN GENERAL (by extracting the template with Expression Blend, customize it and then tell the TileView to use our template for its items).
    But since we want to have two different colors (depending on a selection) this is only half of the job...
    Now we´re stuck with this:
    How can we inherit from RadTileViewItem, add a new property "IsSelected" and then use THIS property inside a trigger or Binding to switch between different header colors (or complete style templates)?

    Any help or hints are happily appreciated, so thanx in advance.
    Ron
  2. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 16 Dec 2010 Link to this post

    Hi Ronald Bouras,

     You'll have do a couple of things:
    - Create a custom control that inherits RadTileViewItem
    - Set it a template in the Generic.xaml file 
    - Add the new DependencyProperties
    - Implement some selection logic(click, drag etc)
    I've created you a sample project, so could you please examine it and if you have further questions feel free to ask.

    Greetings,
    Zarko
    the Telerik team
    Browse the videos here>> to help you get started with RadControls for WPF
  3. UI for WPF is Visual Studio 2017 Ready
  4. Ronald Bouras
    Ronald Bouras avatar
    11 posts
    Member since:
    Jun 2010

    Posted 17 Dec 2010 Link to this post

    Hi Zarko,
    thank you for your post.
    I managed to extend your great sample to some backcolor modifications and it works very well in the unbound mode of your sample.
    What still throws exceptions is, trying to use the style in bound mode, because at some point I will have to tell the TileView, to use our style when creating tiles, so I thought this code would be appropriate:
    <telerik:RadTileView HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Contacts}" >
        <telerik:RadTileView.ItemContainerStyle>
            <Style TargetType="local:MyItem">
                <Setter Property="MinimizedHeight" Value="175" />
            </Style>
        </telerik:RadTileView.ItemContainerStyle>

    But now at runtime I get an exception saying something like "A style provided for the type 'TileControl' cannot be applied to RadTileViewItem", in original german: "Ein für den Typ "TileControl" vorgesehener Stil kann nicht auf den Typ "RadTileViewItem" angewendet werden."

    Is this the wrong place to tell the TileView which type of Tiles it should use?

    Thanx for more ideas on that in advance,
    Ron
  5. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 20 Dec 2010 Link to this post

    Hi Ronald Bouras,

     From the code snippet that you've provided I couldn't reproduce the exception. I updated my sample project to use binding and styles, but everything works fine for me.
    I've attached my updated project, so could you please examine it and see if it helps you with your problem.
    If you still have that issue I'll ask you to send me a sample project that reproduces it.

    Greetings,
    Zarko
    the Telerik team
    Browse the videos here>> to help you get started with RadControls for WPF
  6. Ronald Bouras
    Ronald Bouras avatar
    11 posts
    Member since:
    Jun 2010

    Posted 21 Dec 2010 Link to this post

    Hi Zarko,
    thank you for your reply.

    The difference between our projects is the ItemSource of our RadTileView, since your code is still binding to a collection of the customized RadTileViewItem:
    private ObservableCollection<MyItem> items;
      
    public MainPageViewModel()
    {
        items = new ObservableCollection<MyItem>();
        Items.Add(new MyItem() { Header = "One" });
        Items.Add(new MyItem() { Header = "Two" });
        Items.Add(new MyItem() { Header = "Three" });
        Items.Add(new MyItem() { Header = "Four" });
    }

    But of course we don´t want to bind to a collection of controls but to data rows coming from a database.
    You can easily reproduce our exception when you try to bind the RadTileView to "Contacts" instead of "Items", using this code in the MainPageViewModel:
    public BindingList<Contact> Contacts { get; set; }
      
    public MainPageViewModel()
    {
       Contacts = new BindingList<Contact>();
       Contacts.Add(new Contact("Donald Duck"));
       Contacts.Add(new Contact("Mickey Mouse"));
       Contacts.Add(new Contact("Arnold Schwarzenegger"));
    }

    and the class contact:
    namespace TileViewWithSelection
    {
       public class Contact
       {
          public string Name { get; set; }
      
          public Contact(string name)
          {
             Name = name;
          }
       }
    }

    Thanx in advance for further help on this,
    Ron
  7. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 22 Dec 2010 Link to this post

    Hi Ronald Bouras,

     The problem is that when you give a business object (like Contact) to the RadTileView it automatically wraps it inside a RadTileViewItem. To change this behavior you should use a custom control that inherits the RadTileView and overrides two of his functions(GetContainerForItemOverride and IsItemItsOwnContainerOverride).
    I've updated the sample project, so could you please examine it and if you have further questions feel free to ask.
    Note: In order to be easier to set a Foreground to the header I've replaced the header ContentPresenter with a TextBlock and the Foreground is now changed with visual states.

    All the best,
    Zarko
    the Telerik team
    Browse the videos here>> to help you get started with RadControls for WPF
  8. Ronald Bouras
    Ronald Bouras avatar
    11 posts
    Member since:
    Jun 2010

    Posted 27 Dec 2010 Link to this post

    Hi Zarko,

    thank you very much indeed for the missing hint - it works like a charm now :-)
    We managed to make the header background color work for the selection, too.

    To make it perfect, we would like to adjust two little more things

    1. Header text width
      As you can see from the screenshot attached, the size of the header does not consider the maximize button on the right.
      We want to avoid the text to "overrun" the button position bat always stop a little before it.
      We tried everything from padding and margin to binding the textbox´s width to the tiles actual width, but we will need a tip here.
    2. Data bound header image
      We have added a symbol in the header as well. This symbol works perfectly with a static image but throws an exception when bound to the business objects (it´s not a converter problem - we checked that).
      Could you please check, what´s possibly wrong with our approach to that ?

    <Border x:Name="GripBarElement">
        <StackPanel Orientation="Horizontal" x:Name="HeaderPanel" >
            <Image x:Name="HeaderSymbol"
                    Height="16" Width="16" Stretch="UniformToFill" Margin="5,0"
                    Source="{TemplateBinding HeaderSymbol}"
            />
            <TextBlock x:Name="HeaderText"
                Foreground="{TemplateBinding HeaderForeground}"
                Text="{TemplateBinding Header}" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Center" />
        </StackPanel>
    and the corresponding c# class code:
    ///HeaderSymbolProperty
       /// <summary></summary>
       public static readonly DependencyProperty HeaderSymbolProperty =
          DependencyProperty.Register("HeaderSymbol", typeof(Image), typeof(TileControl));
      
    ///HeaderSymbol
       /// <summary>Liefert das Symbol für den Header oder legt dieses fest</summary>
       public Image HeaderSymbol
       {
          get { return (Image)GetValue(HeaderSymbolProperty); }
          set { SetValue(HeaderSymbolProperty, value); }
       }

    and in the main window xaml the corresponding usage would be:
    <Style TargetType="local:TileControl">
        <Setter Property="Header" Value="{Binding Name}"></Setter>
        <Setter Property="HeaderSymbol" 
                              Value="{Binding Symbol, Converter={StaticResource binaryToBitmapConverter}}"></Setter>
        <Setter Property="MinimizedHeight" Value="175" />
    </Style>


    Thank you very much in advance for your comments on that,
    Best regards
    Ron
  9. Answer
    Zarko
    Admin
    Zarko avatar
    755 posts

    Posted 29 Dec 2010 Link to this post

    Hello Ronald Bouras,

     The easiest solution for your first problems is to put the GripBarElement and the MaximizeToggleButton in two different grid columns like that:

    <Grid MinHeight="28">
       <Grid.ColumnDefinitions>
           <ColumnDefinition />
           <ColumnDefinition Width="Auto" />
       </Grid.ColumnDefinitions>
       <Border x:Name="GripBarElement" Background="Transparent">
           <StackPanel Orientation="Horizontal" x:Name="HeaderPanel">
               <Image x:Name="HeaderSymbol" Height="16" Width="16"
                      Stretch="UniformToFill" Margin="5,0"
                      Source="{TemplateBinding HeaderSymbol, Converter={StaticResource myConverter}}" />
               <TextBlock x:Name="HeaderText"
                          Foreground="{TemplateBinding HeaderForeground}"
                          Text="{TemplateBinding Header}"
                          HorizontalAlignment="Left" VerticalAlignment="Center" />
           </StackPanel>
       </Border>
       <ToggleButton x:Name="MaximizeToggleButton" Grid.Column="1"
                     HorizontalAlignment="Right" Height="17"
                     VerticalAlignment="Center" Width="17">
                     ...
       </ToggleButton>
    </Grid>
    For your second problem it depends on how you store the image in your business object(as a path to a file, as a binary array, as an Image, etc). From the code snippets  that you've provided I can see a possible problem - the Source property of the Image class takes a Uri or a String, but you bind it to a DependencyProperty that's of type Image.
    I've updated the sample project so that it works with binding if you keep a path to the desired image in your business object. Could you please examine and if you have further questions feel free to ask.


    Kind regards,
    Zarko
    the Telerik team
    Browse the videos here>> to help you get started with RadControls for WPF
  10. Ronald Bouras
    Ronald Bouras avatar
    11 posts
    Member since:
    Jun 2010

    Posted 07 Jan 2011 Link to this post

    Hi Zarko,

    thank you for all your help in this matter - the control now works fine and is exactly what we had in mind.

    All the best to all of you guys in the team for this new year.
    Ron
Back to Top
UI for WPF is Visual Studio 2017 Ready