2013-05-06 105 views
2

我对tabcontrol控件有问题。值不在ObservableCollection中的预期范围内<TabItems>

我使用绑定和转换器动态添加项目到tabcontrol。

当加入第二的TabItem得到下面的异常(见下文代码): 值不在所述预期范围内

及其堆栈跟踪:

вMS.Internal.XcpImports.CheckHResult(UInt32的小时) вMS.Internal.XcpImports.SetValue(IManagedPeerBase OBJ,的DependencyProperty属性,DependencyObject的DOH) вMS.Internal.XcpImports.SetValue(IManagedPeerBase DOH,的DependencyProperty属性,对象OBJ) вSystem.Windows.DependencyObject.SetObjectValueToCore(的DependencyProperty DP ,对象值) вSystem.Windows.DependencyObject.SetEffectiveValue(的DependencyProperty属性,EffectiveValueEntry & newEntry,对象newValue)以 вSystem.Windows.DependencyObject.UpdateEffectiveValue(的DependencyProperty属性,EffectiveValueEntry oldEntry,EffectiveValueEntry & newEntry,ValueOperation操作) вSystem.Windows.DependencyObject .SetValueInternal(DependencyProperty dp,Object value,Boolean allowReadOnlySet)SilverlightApplication1.Services.TabConverter.Convert(Object value,Type targetType,Object parameter,CultureInfo culture)

(System.Windows.Controls.ContentControl.set_Content(Object value)

MainPage xaml:

<UserControl x:Class="SilverlightApplication1.MainPage" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d" 
     d:DesignHeight="1024" 
     d:DesignWidth="1280" 
     xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
     xmlns:local="clr-namespace:SilverlightApplication1.Services"> 

<UserControl.Resources> 
    <local:TabConverter x:Key="tabConverter" /> 
</UserControl.Resources> 

<Grid x:Name="LayoutRoot" 
     Background="White"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="1*" /> 
     <ColumnDefinition Width="4*" /> 
    </Grid.ColumnDefinitions> 
    <ListBox SelectionChanged="ListBox_SelectionChanged"> 
     <ListBoxItem Content="ViewA"></ListBoxItem> 
     <ListBoxItem Content="ViewB"></ListBoxItem> 
    </ListBox> 
    <sdk:TabControl Grid.Column="1" 
        ItemsSource="{Binding Tabs, Converter={StaticResource tabConverter}}" /> 
</Grid> 

代码的MainPage隐藏:

public partial class MainPage : UserControl { 
    ViewModel viewModel = new ViewModel(); 

    public MainPage() { 
     InitializeComponent(); 
     this.DataContext = viewModel; 
    } 

    private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { 
     try { 
      viewModel.Tabs.Add(new TabItemModel() { 
       Header = "New Tab", 
       Content = new Grid() 
      }); 

      // sdk:tabcontrol does not listen CollectionChanged of viewModel.Tabs. 
      // thats why: 
      viewModel.Tabs = viewModel.Tabs; 
     } catch (Exception) { } 
    } 
} 

数据模型:

public class TabItemModel { 
    public string Header { get; set; } 
    public UIElement Content { get; set; } 
} 

视图模型:

public class ViewModel:INotifyPropertyChanged { 
    ObservableCollection<TabItemModel> tabs = new ObservableCollection<TabItemModel>(); 
    public ObservableCollection<TabItemModel> Tabs { 
     get { return tabs; } 
     set { tabs = value; OnPropertyChanged(PropertyNames.Tabs); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    void OnPropertyChanged(string property) { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 

    class PropertyNames { 
     public const string Tabs = "Tabs"; 
    } 
} 

标签转换器:

public class TabConverter : IValueConverter { 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
     try { 
      var object_data = value as ObservableCollection<TabItemModel>; 
      var result = new List<TabItem>(); 
      foreach (var item in object_data) { 
       result.Add(new TabItem() { 
        Header = item.Header, 
        Content = item.Content // if comment this, everything works 
       }); 
      } 
      return result; 
     } catch (Exception e) { 
      MessageBox.Show(e.StackTrace, e.Message, MessageBoxButton.OK); 
      return null; 
     } 
    } 

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

+1发布工作代码,这是一个简单的复制粘贴:)我放弃了一个小时后,因为它只是不工作。伊莫这是一个有缺陷的控制。看看@Sphinxxx答案,我认为你可以使用的是在链接* Silverlight的TabControl与数据绑定* – Silvermind 2013-05-06 23:15:41

回答

3

你的问题是你在你的数据模型中保留UIElement

在MVVM,这是一个很大的禁忌本身,但这里的具体问题是,当你添加第二个TabItemModel和转换器重新创建所有需要TabItem秒,第一 TabItemModel的内容放置在两个的TabItems马上一分钟。一个UI元素只能有一个父项。

这里最“MVVM”的解决方案是将UI元素保留在数据模型之外。相反,只需在TabItemModel.Content中保留一些原始数据并在xaml中使用DataTemplate即可表示该数据的UI。

如果需要保持UI元素在数据模型中,我建议你看看这个扭捏的TabControl,修正了越野车的Silverlight的TabControl,并不需要一个转换器才能正常工作:Silverlight TabControl with data binding(从取这个SO帖子讨论了同样的问题:Bind a Silverlight TabControl to a Collection

+0

只是检查这个问题,并发现ItemTemplate属性不工作,因为人们会期望的Silverlight sdk' TabControl'。 – Silvermind 2013-05-06 22:55:41

+0

@Silvermind:是的,显然是这样。我在我的答案中发布的两个链接解决了确切的问题(尽管我没有尝试vorrtex'自己调整TabControl)。 – Sphinxxx 2013-05-06 23:08:07

+0

我发现在同一个人的更新文章中解决了“SelectedItem”问题:http://vortexwolf.wordpress.com/2011/07/27/silverlight-tabcontrol-with-scrolling-and-with-新选项卡按钮/它看起来像是OP需要的一个很好的控制。 – Silvermind 2013-05-06 23:11:51

相关问题