将Silverlight TabControl绑定到集合

5
我在ViewModel中有一组Model对象。我想将TabControl绑定到这些对象,并使用DataTemplate从Model对象中提取信息。但是当我尝试这样做时,我收到以下错误信息:无法将类型为Model的对象强制转换为类型为TabItem的对象。经过一段时间的寻找解决方案,我发现了以下内容:
  1. Silverlight TabControl已经损坏。使用ListBox和ContentControl的组合来模仿TabControl的行为。(这意味着我必须将ListBox装扮成TabControl)

  2. TabControl没有覆盖PrepareContainerForItemOverride方法,解决方案是创建一个转换器。(不是很好,因为我需要在转换器中指定被转换对象的类型)

有人知道更好的解决方案吗?

XAML

<sdk:TabControl ItemsSource="{Binding Items, ElementName=MyControl}">
        <sdk:TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </sdk:TabControl.ItemTemplate>
    </sdk:TabControl>

C#

public ObservableCollection<Model> Items { get; set; }

public ViewModel()

    Items = new ObservableCollection<Model>{
        new Model { Name = "1"},
        new Model { Name = "2"},
        new Model { Name = "3"},
        new Model { Name = "4"}
    };
}

建议使用的转换工具

public class TabConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        List<TabSource> source = value as List<TabSource>;
        if (source != null)
        {
            List<TabItem> result = new List<TabItem>();
            foreach (TabSource tab in source)
            {
                result.Add(new TabItem()
                {
                    Header = tab.Header,
                    Content = tab.Content
                });
            }
            return result;
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我已经创建了扩展选项卡控件,它不需要转换器,并且可以正确地使用ObservableCollection类。http://vortexwolf.wordpress.com/2011/04/09/silverlight-tabcontrol-with-data-binding/ - vortexwolf
1个回答

2
创建转换器
public class SourceToTabItemsConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            try
            {
                var source = (IEnumerable)value;
                if (source != null)
                {
                    var controlTemplate = (ControlTemplate)parameter;

                    var tabItems = new List<TabItem>();

                    foreach (object item in source)
                    {
                        PropertyInfo[] propertyInfos = item.GetType().GetProperties();

                        //тут мы выбираем, то поле которое будет Header. Вы должны сами вводить это значение.
                        var propertyInfo = propertyInfos.First(x => x.Name == "name");

                        string headerText = null;
                        if (propertyInfo != null)
                        {
                            object propValue = propertyInfo.GetValue(item, null);
                            headerText = (propValue ?? string.Empty).ToString();
                        }

                        var tabItem = new TabItem
                                          {
                                              DataContext = item,
                                              Header = headerText,
                                              Content =
                                                  controlTemplate == null
                                                      ? item
                                                      : new ContentControl { Template = controlTemplate }
                                          };

                        tabItems.Add(tabItem);
                    }

                    return tabItems;
                }
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// ConvertBack method is not supported
        /// </summary>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException("ConvertBack method is not supported");
        }

创建控件模板:
<ControlTemplate x:Key="MyTabItemContentTemplate">
            <StackPanel>
                <TextBlock Text="{Binding Path=name}" />
            </StackPanel>
        </ControlTemplate>

绑定转换和控件模板

<controls:TabControl  x:Name="tabControl"
        ItemsSource="{Binding ElementName=tabControl, 
                              Path=DataContext, 
                              Converter={StaticResource ConverterCollectionToTabItems}, 
                              ConverterParameter={StaticResource MyTabItemContentTemplate}}">
        </controls:TabControl>

本文内容摘自博客binding-tabcontrol


1
请用英语总结您的博客文章内容。此外,当您链接到您的博客或任何您所属的网站、产品或项目时,您需要披露这是您自己的作品。请参阅FAQ中的“我可以在这里推广我所属的产品或网站吗?”部分。 - Bill the Lizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接