How bind TabControl?

2019-05-22 15:49发布

xaml

<controls:TabControl x:Name="tabControlRoom" Grid.Row="1" Grid.Column="1" d:LayoutOverrides="Width, Height" ItemsSource="{Binding}" >
            <controls:TabControl.ItemTemplate>
                <DataTemplate>
                    <controls:TabItem Header="{Binding name}">
                        <StackPanel Margin="10" Orientation="Horizontal">

                        </StackPanel>
                    </controls:TabItem>
                </DataTemplate>
            </controls:TabControl.ItemTemplate>
        </controls:TabControl>

and code

m_roomContext.Load(m_roomContext.GetRoomQuery());
                tabControlRoom.DataContext = m_roomContext.Rooms;

when I open this page, then there is all the elements, but a second later I see only a white screen

error:

load operation failed for query 'GetRoom'. Unable to cast object of type 'Web.Room' to type 'System.Windows.Controls.TabItem'/'

2条回答
【Aperson】
2楼-- · 2019-05-22 16:22

Create converter

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");
        }

Create ControlTemplate:

<ControlTemplate x:Key="MyTabItemContentTemplate">
            <StackPanel>
                <TextBlock Text="{Binding Path=name}" />
            </StackPanel>
        </ControlTemplate>

And binding convert, controltemplate

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

taken from the blog binding-tabcontrol

查看更多
乱世女痞
3楼-- · 2019-05-22 16:31

When binding the TabControl there are two things you need to accomplish, one is the header content for the TabItem the other is the content for the selected TabItem, which is generally another user control.

The way have I've solved this in the past is to bind ItemsSource of the TabControl to a collection of view models, and to provide two data templates, one to supply the header content for the TabItem, an the other to supply the content for the selected TabItem, which maps to a view.

<Window.Resources>
    <DataTemplate x:Key="ItemTemplate">
        <TextBlock Text="{Binding Title}" />
    </DataTemplate>

    <DataTemplate x:Key="ContentTemplate">
        <local:SampleView />
    </DataTemplate>
</Window.Resources>

<Grid>
    <TabControl 
        ItemsSource="{Binding SampleViewModels}" 
        ItemTemplate="{StaticResource ItemTemplate}"
        ContentTemplate="{StaticResource ContentTemplate}"
        SelectedIndex="0"
        />
</Grid>
查看更多
登录 后发表回答