This is a migrated thread and some comments may be shown as answers.

SelectionBoxItemTemplate is sometimes applied too late

4 Answers 125 Views
ComboBox
This is a migrated thread and some comments may be shown as answers.
hwsoderlund
Top achievements
Rank 1
hwsoderlund asked on 05 Jun 2009, 03:02 PM
Sometimes, and I'm not exactly sure when, the SelectionBoxItemTemplate is not applied until the combobox is opened, even though an item is selected. See the code below.

 
<UserControl x:Class="TelerikTestProject.SilverlightControl4" 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:telerikbase="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" 
             xmlns:telerikinput="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input" 
             xmlns:teleriknav="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation" 
             xmlns:local="clr-namespace:TelerikTestProject" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             Width="400" 
             Height="300"
    <Grid x:Name="LayoutRoot" 
          Background="White"
 
        <Grid.Resources> 
            <telerikbase:ContainerBindingCollection x:Name="UserItemBindings"
                <telerikbase:ContainerBinding PropertyName="IsSelected" 
                                              Binding="{Binding IsSelected, Mode=TwoWay}" /> 
            </telerikbase:ContainerBindingCollection> 
 
            <DataTemplate x:Key="UserItemTemplate" 
                          telerikbase:ContainerBinding.ContainerBindings="{StaticResource UserItemBindings}"
                <TextBlock Text="{Binding FirstName}"></TextBlock> 
            </DataTemplate> 
 
            <DataTemplate x:Key="UserItemTemplate_SelectionBox"
                <TextBlock Text="{Binding FirstName}"></TextBlock> 
            </DataTemplate> 
 
        </Grid.Resources> 
 
        <telerikinput:RadComboBox x:Name="RCBUsers" 
                                  ItemsSource="{Binding Users}" 
                                  VerticalAlignment="Top" 
                                  HorizontalAlignment="Left" 
                                  ItemTemplate="{StaticResource UserItemTemplate}" 
                                  SelectionBoxItemTemplate="{StaticResource UserItemTemplate_SelectionBox}"
        </telerikinput:RadComboBox> 
 
    </Grid> 
</UserControl> 
 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 
using Telerik.Windows.Controls; 
using System.Collections.ObjectModel; 
 
namespace TelerikTestProject 
    public partial class SilverlightControl4 : UserControl 
    { 
        public SilverlightControl4() 
        { 
            InitializeComponent(); 
 
            var users = UserInfo2.Get10(); 
            users[3].IsSelected = true
 
            var container = new UserContainer() { Users = users }; 
 
            this.DataContext = container; 
        } 
    } 
 
    public class UserContainer 
    { 
        public ObservableCollection<UserInfo2> Users { getset; } 
    } 
 
    public class UserInfo2 
    { 
        public string FirstName { getset; } 
        public bool IsSelected { getset; } 
 
        public UserInfo2() 
        { 
        } 
 
        public static ObservableCollection<UserInfo2> Get10() 
        { 
            ObservableCollection<UserInfo2> users = new ObservableCollection<UserInfo2>(); 
 
            for (int i = 0; i < 100; i++) 
            { 
                users.Add(new UserInfo2() 
                { 
                    FirstName = String.Format("FirstName {0}", i), 
                }); 
            } 
 
            return users; 
        } 
    } 
 



4 Answers, 1 is accepted

Sort by
0
Accepted
Valeri Hristov
Telerik team
answered on 08 Jun 2009, 02:54 PM
Hi Henrik,

The problem is that the RadComboBoxItem containers are generated after the combo box dropdown is opened for the first time. If the containers are not generated, the container bindings are not applied and the combo box does not "know" which data item is selected. The correct way to initially select an item is through one of the following properties: SelectedItem, SelectedIndex, SelectedValue.

Regards,
Valeri Hristov
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
hwsoderlund
Top achievements
Rank 1
answered on 12 Jun 2009, 08:20 AM
Ok, I see the problem. Comboboxes in silverlight are a real pain in the butt, aren't they? Anyway, I thought I'd share with you a decent solution to the problem. It involves a converter that uses reflection, so it's not very performant with a large number of items, but it works ok when you bind often against collections of items where the items have a boolean property that is true for the selected item and false for the rest. Here's an example:

<UserControl x:Class="TelerikTestProject.SilverlightControl4" 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:telerikbase="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" 
             xmlns:telerikinput="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Input" 
             xmlns:teleriknav="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation" 
             xmlns:local="clr-namespace:TelerikTestProject" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             Width="400" 
             Height="300"
    <Grid x:Name="LayoutRoot" 
          Background="White"
 
        <Grid.Resources> 
 
            <local:SelectedItemConverter x:Key="SelectedItemConverter"></local:SelectedItemConverter> 
             
            <telerikbase:ContainerBindingCollection x:Name="UserItemBindings"
                <telerikbase:ContainerBinding PropertyName="IsSelected" 
                                              Binding="{Binding IsSelected, Mode=TwoWay}" /> 
            </telerikbase:ContainerBindingCollection> 
 
            <DataTemplate x:Key="UserItemTemplate" 
                          telerikbase:ContainerBinding.ContainerBindings="{StaticResource UserItemBindings}"
                <TextBlock Text="{Binding FirstName}"></TextBlock> 
            </DataTemplate> 
 
            <DataTemplate x:Key="UserItemTemplate_SelectionBox"
                <TextBlock Text="{Binding FirstName}"></TextBlock> 
            </DataTemplate> 
 
        </Grid.Resources> 
 
        <telerikinput:RadComboBox x:Name="RCBUsers" 
                                  ItemsSource="{Binding Users}" 
                                  SelectedItem="{Binding Users, Converter={StaticResource SelectedItemConverter}, ConverterParameter='IsSelected'}" 
                                  VerticalAlignment="Top" 
                                  HorizontalAlignment="Left" 
                                  ItemTemplate="{StaticResource UserItemTemplate}" 
                                  SelectionBoxItemTemplate="{StaticResource UserItemTemplate_SelectionBox}"
        </telerikinput:RadComboBox> 
 
    </Grid> 
</UserControl> 
 

And the code:
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 
using Telerik.Windows.Controls; 
using System.Collections.ObjectModel; 
using System.Collections; 
using System.Windows.Data; 
using System.Globalization; 
 
namespace TelerikTestProject 
    public partial class SilverlightControl4 : UserControl 
    { 
        public SilverlightControl4() 
        { 
            InitializeComponent(); 
 
            var users = UserInfo2.GetMany(); 
            users[98].IsSelected = true
 
            var container = new UserContainer() { Users = users }; 
 
            this.DataContext = container; 
        } 
    } 
 
    public class UserContainer 
    { 
        public ObservableCollection<UserInfo2> Users { getset; } 
    } 
 
    public class UserInfo2 
    { 
        public string FirstName { getset; } 
 
        public bool IsSelected { getset; } 
 
        public UserInfo2() 
        { 
        } 
 
        public static ObservableCollection<UserInfo2> GetMany() 
        { 
            ObservableCollection<UserInfo2> users = new ObservableCollection<UserInfo2>(); 
 
            for (int i = 0; i < 100; i++) 
            { 
                users.Add(new UserInfo2() 
                { 
                    FirstName = String.Format("FirstName {0}", i), 
                }); 
            } 
 
            return users; 
        } 
    } 
 
    public class SelectedItemConverter : IValueConverter 
    { 
        #region IValueConverter Members 
 
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
        { 
            var propName = parameter.ToString(); 
 
            if (value is IEnumerable) 
            { 
                var selectableItems = (from object val in (value as IEnumerable).AsQueryable() select val).Cast<object>().ToList(); 
 
                foreach (object obj in selectableItems) 
                { 
                    var pi = obj.GetType().GetProperty(propName); 
                    var isSelected = (bool)pi.GetValue(obj, null); 
 
                    if (isSelected) 
                        return obj; 
                } 
            } 
 
            return null
        } 
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
        { 
            throw new NotImplementedException(); 
        } 
        #endregion 
    } 
 


0
Valeri Hristov
Telerik team
answered on 12 Jun 2009, 10:18 AM
Hello Henrik,

I guess that you could simply implement an interface ISelectable in each data item, that will contain a single property IsSelected, then instead of using Reflection, you could cast the items to the interface and directly check the IsSelected property. But in this case you will lose the flexibility of the converter parameter.

Other option would be, if your data source collections are generic, to use the classes in the System.Linq.Expressions namespace to build a dynamic Linq expression, that will be compiled into a typed lambda, that will be executed against each data item. This would provide great performance increase while keeping the flexibility. Unfortunately this is pretty advanced stuff and it will take me some time to provide an example.

Sincerely yours,
Valeri Hristov
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
hwsoderlund
Top achievements
Rank 1
answered on 12 Jun 2009, 10:32 AM
Using an interface is what occured to me first, but the problem is that I'm binding against server-side entities that are duplicated on the client using "add service reference", so I would then have to use partial classes to implement the interface for all these entities (and there are lots of them).

Doing it with a Linq expression sounds interesting though. We have a guy who knows a lot about pre-compiling expressions. I'll talk to him and see if he can help me.

Thanks,
/Henrik
Tags
ComboBox
Asked by
hwsoderlund
Top achievements
Rank 1
Answers by
Valeri Hristov
Telerik team
hwsoderlund
Top achievements
Rank 1
Share this question
or