指定类型的 WPF 绑定 (ItemTemplate)

WPF Binding with type specified (ItemTemplate)

我的 WPF 应用程序中有一个列表框,我想为其创建自定义 ItemTemplate。

当我在模板中绑定到其属性时指定 ListBoxItem 的类型时,出现以下异常:

代码:

<ListBox SelectionMode="Multiple" ItemsSource="{Binding CashTypes}" IsSynchronizedWithCurrentItem="True">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=(local:CashTypeEnumViewModel.IsSelected)}"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding (local:CashTypeEnumViewModel.CashType)}"></TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

异常:

System.Windows.Markup.XamlParseException occurred
  HResult=-2146233087
  LineNumber=0
  LinePosition=0
  Message=Key cannot be null.
Parameter name: key
  Source=PresentationFramework
  StackTrace:
       at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
       at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
       at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
       at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
       at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
       at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
       at System.Windows.FrameworkElement.ApplyTemplate()
       at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       at System.Windows.UIElement.Measure(Size availableSize)
       at System.Windows.Controls.Border.MeasureOverride(Size constraint)
       at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       at System.Windows.UIElement.Measure(Size availableSize)
       at System.Windows.Controls.Control.MeasureOverride(Size constraint)
       at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       at System.Windows.UIElement.Measure(Size availableSize)
       at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Double& computedUniformOrAverageContainerPixelSize, Boolean& computedAreContainersUniformlySized, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren)
       at System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable`1& lastPageSafeOffset, List`1& previouslyMeasuredOffsets, Nullable`1& lastPagePixelSize, Boolean remeasure)
       at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint)
       at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
       at System.Windows.UIElement.Measure(Size availableSize)
       at System.Windows.ContextLayoutManager.UpdateLayout()
       at System.Windows.UIElement.UpdateLayout()
       at System.Windows.Interop.HwndSource.SetLayoutSize()
       at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
       at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
       at System.Windows.Window.SetRootVisual()
       at System.Windows.Window.SetRootVisualAndUpdateSTC()
       at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
       at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
       at System.Windows.Window.CreateSourceWindowDuringShow()
       at System.Windows.Window.SafeCreateWindowDuringShow()
       at System.Windows.Window.ShowHelper(Object booleanBox)
       at System.Windows.Window.Show()
       at XY.ApplicationBootstrapper.InitializeShell() in C:\_git\XY\Startup\ApplicationBootstrapper.cs:line 85
  InnerException: 
       HResult=-2147467261
       Message=Key cannot be null.
Parameter name: key
       ParamName=key
       Source=System
       StackTrace:
            at System.Collections.Specialized.ListDictionary.get_Item(Object key)
            at System.Collections.Specialized.HybridDictionary.get_Item(Object key)
            at System.ComponentModel.PropertyChangedEventManager.AddListener(INotifyPropertyChanged source, String propertyName, IWeakEventListener listener, EventHandler`1 handler)
            at System.ComponentModel.PropertyChangedEventManager.AddHandler(INotifyPropertyChanged source, EventHandler`1 handler, String propertyName)
            at MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32 k, Object newO, Object parent)
            at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange)
            at MS.Internal.Data.ClrBindingWorker.AttachDataItem()
            at System.Windows.Data.BindingExpression.Activate(Object item)
            at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
            at System.Windows.Data.BindingExpression.AttachOverride(DependencyObject target, DependencyProperty dp)
            at System.Windows.Data.BindingExpressionBase.OnAttach(DependencyObject d, DependencyProperty dp)
            at System.Windows.StyleHelper.GetInstanceValue(UncommonField`1 dataField, DependencyObject container, FrameworkElement feChild, FrameworkContentElement fceChild, Int32 childIndex, DependencyProperty dp, Int32 i, EffectiveValueEntry& entry)
            at System.Windows.StyleHelper.GetChildValueHelper(UncommonField`1 dataField, ItemStructList`1& valueLookupList, DependencyProperty dp, DependencyObject container, FrameworkObject child, Int32 childIndex, Boolean styleLookup, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot)
            at System.Windows.StyleHelper.GetChildValue(UncommonField`1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList`1& childRecordFromChildIndex, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot)
            at System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList`1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry)
            at System.Windows.StyleHelper.ApplyTemplatedParentValue(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList`1& childRecordFromChildIndex, DependencyProperty dp, FrameworkElementFactory templateRoot)
            at System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList`1& childRecordFromChildIndex, Boolean isDetach, FrameworkElementFactory templateRoot)
            at System.Windows.FrameworkTemplate.InvalidatePropertiesOnTemplate(DependencyObject container, Object currentObject)
            at System.Windows.FrameworkTemplate.HandleBeforeProperties(Object createdObject, DependencyObject& rootObject, DependencyObject container, FrameworkElement feContainer, INameScope nameScope)
            at System.Windows.FrameworkTemplate.<>c__DisplayClass45_0.<LoadOptimizedTemplateContent>b__2(Object sender, XamlObjectEventArgs args)
            at System.Xaml.XamlObjectWriter.OnBeforeProperties(Object value)
            at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
            at System.Xaml.XamlObjectWriter.WriteEndObject()
            at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
            at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
       InnerException: 

只要我不指定类型,一切正常…

代码:

<ListBox SelectionMode="Multiple" ItemsSource="{Binding CashTypes}" IsSynchronizedWithCurrentItem="True">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=(local:CashTypeEnumViewModel.IsSelected)}"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding CashType}"></TextBlock>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

如何让它与指定的类型一起工作?

类型的正确位置是 DataTemplate

DataType 属性
<DataTemplate DataType="{x:Type local:CashTypeEnumViewModel}>
    <TextBlock Text="{Binding CashType}"/>
</DataTemplate>