C# Can';t将MS.Internal.NamedObject类型的对象转换为System.Windows.Datatemplate

C# Can';t将MS.Internal.NamedObject类型的对象转换为System.Windows.Datatemplate,c#,wpf,C#,Wpf,我想更改基于枚举的图标 我已经为我的UserControl创建了一个名为CallControlViewModel的新viewmodel public class CallControlViewModel : BaseViewModel { private InputTypeEnum _inputTypeEnum; public CallControlViewModel() { } public InputTypeEnum InputType

我想更改基于枚举的图标

我已经为我的UserControl创建了一个名为CallControlViewModel的新viewmodel

public class CallControlViewModel : BaseViewModel
{
    private InputTypeEnum _inputTypeEnum;

    public CallControlViewModel()
    {

    }

    public InputTypeEnum InputType
    {
        get { return _inputTypeEnum; }
        set
        {
            if (_inputTypeEnum != value)
            {
                _inputTypeEnum = value;
                NotifyPropertyChanged("InputType");
            }
        }
    }
}
这是baseViewModel

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Notify of Property Changed event
    /// </summary>
    /// <param name="propertyName"></param>
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }        
}
用户控制背后的代码

public partial class CallControl : UserControl
{
    private CallControlViewModel callControlViewModel;

    public CallControl()
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(CallControl_Loaded);
    }

    void CallControl_Loaded(object sender, RoutedEventArgs e)
    {
        callControlViewModel = new CallControlViewModel();
        this.DataContext = callControlViewModel;
    }

    private void CallBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        InputTypeEnum type = DecideInputType();
        callControlViewModel.InputType = type;
    }

    private InputTypeEnum DecideInputType()
    {
        if(string.IsNullOrEmpty(CallBox.Text))
        {
            return InputTypeEnum.Empty;
        }

        if (IsNumeric(CallBox.Text))
        {
            return InputTypeEnum.Number;
        }

        return InputTypeEnum.Text;
    }
这是我的Xaml:

<UserControl.Resources>
    <Style x:Key="InputTypeIndicatorStyle" TargetType="{x:Type ContentControl}">
    <Style.Triggers>
           <DataTrigger Binding="{Binding InputType}" Value="0">
               <Setter Property="ContentTemplate" Value="{StaticResource ResourceKey=NumberIndicator}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding InputType}" Value="1">
                <Setter Property="ContentTemplate" Value="{StaticResource ResourceKey=NumberIndicator}" />
            </DataTrigger>
            <DataTrigger Binding="{Binding InputType}" Value="2">
                <Setter Property="ContentTemplate" Value="{StaticResource ResourceKey=TextIndicator}" />
             </DataTrigger>
            </Style.Triggers>
        </Style>

        <DataTemplate x:Key="NumberIndicator">
            <Border x:Name="CallIconBorder" Width="35" BorderThickness="1,0,0,0" Background="#353535" 
                    BorderBrush="#5d5d5d" MouseLeftButtonDown="CallIconBorder_MouseLeftButtonDown" Style="{StaticResource CallBorderStyle}" >
                <Image StretchDirection="DownOnly" Margin="5" Source="/Image/call.png"/>
            </Border>
        </DataTemplate>

        <DataTemplate x:Key="TextIndicator">
            <Border x:Name="SearchIconBorder" Width="35" >
                <Image StretchDirection="DownOnly" Margin="5" Source="/Image/search.png"/>
            </Border>
        </DataTemplate>
  </UserControl.Resources>

<DockPanel x:Name="CallControlDock" VerticalAlignment="Bottom" Background="{StaticResource LightGrey}" Height="30">
            <ContentControl Style="{StaticResource InputTypeIndicatorStyle}" DockPanel.Dock="Right" HorizontalAlignment="Right"  />

            <Border x:Name="ClearIconBorder" DockPanel.Dock="Right" Width="20" Visibility="Hidden" VerticalAlignment="Center" Margin="5,0,5,0" 
                    MouseDown="ClearIconBorder_MouseDown" Style="{StaticResource ClearIconStyle}" Opacity="0.5">
                <Image StretchDirection="DownOnly" Source="/Image/close.png" HorizontalAlignment="Left"/>
            </Border>

            <spinners:ucSpinnerCogs x:Name="LoadSpinner" DockPanel.Dock="Right" HorizontalAlignment="Right" Visibility="Collapsed" />

            <TextBox x:Name="CallBox" TextWrapping="Wrap" FontSize="14" FontFamily="Segoe UI Semibold" HorizontalAlignment="Stretch" 
                     Foreground="{StaticResource AlmostWhite}" VerticalAlignment="Center"  
                     GotFocus="CallBox_GotFocus" LostFocus="CallBox_LostFocus" TextChanged="CallBox_TextChanged" KeyDown="CallBox_KeyDown"
                     MouseRightButtonDown="CallBox_MouseRightButtonDown"
                     ContextMenu="{x:Null}">


            </TextBox>
        </DockPanel>
InvalidCastException,无法转换类型为的对象 MS.Internal.NamedObject to System.Windows.Datatemplate


我做错了什么

我确实记得几年前一个项目中的这个问题。我们遇到了同样的问题,并添加了代码来拦截,如下所示:

    /// <summary>
    /// Tests whether the object is the 'NamedObject'. This is placed into 'DataContext' sometimes by WPF as a dummy.
    /// </summary>
    public static bool IsNamedObject(this object obj)
    {
        return obj.GetType().FullName == "MS.Internal.NamedObject";
    }
//
///测试对象是否为“NamedObject”。WPF有时将其作为虚拟对象放入“DataContext”中。
/// 
公共静态bool IsNamedObject(此对象obj)
{
返回obj.GetType().FullName==“MS.Internal.NamedObject”;
}

我们在论坛上发布了一些关于这个的问题,但从来没有得到真正的答案。对了,这篇文章是一条杂乱无章的红鲱鱼。。。对于任何不熟悉这句话的人来说,这意味着你可以忘记所有给出的错误,因为当这是正确的,你不会得到错误。。。这是误导

所以我们走吧。。。使用
触发器
方法:

首先,这里有一个
枚举

public enum TestEnum
{
    None, One, Two, Three
}
现在,属性:

private TestEnum enumInstance = TestEnum.None;

public TestEnum EnumInstance
{
    get { return enumInstance; }
    set { enumInstance = value; NotifyPropertyChanged("EnumInstance"); }
}

private ObservableCollection<TestEnum> enumCollection = 
    new ObservableCollection<TestEnum>() { TestEnum.None, TestEnum.One, 
    TestEnum.Two, TestEnum.Three };

public ObservableCollection<TestEnum> EnumCollection
{
    get { return enumCollection; }
    set { enumCollection = value; NotifyPropertyChanged("EnumCollection"); }
}
private TestEnum enumInstance=TestEnum.None;
公共TestEnumEnumInstance
{
获取{返回枚举实例;}
设置{enumInstance=value;NotifyPropertyChanged(“enumInstance”);}
}
私有ObservableCollection枚举集合=
新的ObservableCollection(){TestEnum.None,TestEnum.One,
TestEnum.2,TestEnum.3};
公共可观测集合枚举集合
{
获取{return enumCollection;}
设置{enumCollection=value;NotifyPropertyChanged(“enumCollection”);}
}
现在,XAML:

<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <Image Width="16" Height="16" Stretch="None" Margin="0,0,0,20">
        <Image.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding EnumInstance}" Value="One">
                        <Setter Property="Image.Source" Value="/WpfApplication2;component/Images/Copy_16.png" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding EnumInstance}" Value="Two">
                        <Setter Property="Image.Source" Value="/WpfApplication2;component/Images/Edit_16.png" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding EnumInstance}" Value="Three">
                        <Setter Property="Image.Source" Value="/WpfApplication2;component/Images/CloseRed_16.png" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
    <ComboBox ItemsSource="{Binding EnumCollection}" SelectedItem="{Binding EnumInstance}" />
</StackPanel>


我相信您可以将此代码转移到您的项目中。最后要注意的是。。。如果您有更多的
enum
值,您最好创建一个
enumtoboolmagesourceconverter
,并用它绑定

适用于遇到相同问题但没有找到其他答案的所有人,这些答案有助于查找到底发生了什么

当您尝试在资源声明之前使用
StaticResource
引用资源时,会出现此问题

在这个问题中,这些资源是
NumberIndicator
textdindicator


这是因为
StaticResource
在编译时工作,不能向前看。因此,要解决这个问题,您可以将资源移动到尚未引用的位置。或者只使用运行时
DynamicResource

我做错了什么?
-你把太多的代码放在了不该放的地方。又回到了破球任务上,嗯@HighCore?:)有趣的是,当我这么做的时候,每个人都对我不屑一顾,所以我放弃了。。。不过,我很高兴有人坚持下去@HighCore你能举个例子说明什么不属于你吗?我还是从wpf开始,所以我想学习。伙计,他不是说你展示了太多的代码,就是说你为这么简单的需求写了太多的代码。他只是想掌握一些东西。救救他!谢谢你的明确的例子!我可以将此代码移植到我的代码中。您摘要中的信息来自何处?
NamedObject
类型来自
DependencyProperty.UnsetValue
,(来自公共.NET源代码)。
private TestEnum enumInstance = TestEnum.None;

public TestEnum EnumInstance
{
    get { return enumInstance; }
    set { enumInstance = value; NotifyPropertyChanged("EnumInstance"); }
}

private ObservableCollection<TestEnum> enumCollection = 
    new ObservableCollection<TestEnum>() { TestEnum.None, TestEnum.One, 
    TestEnum.Two, TestEnum.Three };

public ObservableCollection<TestEnum> EnumCollection
{
    get { return enumCollection; }
    set { enumCollection = value; NotifyPropertyChanged("EnumCollection"); }
}
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
    <Image Width="16" Height="16" Stretch="None" Margin="0,0,0,20">
        <Image.Style>
            <Style>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding EnumInstance}" Value="One">
                        <Setter Property="Image.Source" Value="/WpfApplication2;component/Images/Copy_16.png" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding EnumInstance}" Value="Two">
                        <Setter Property="Image.Source" Value="/WpfApplication2;component/Images/Edit_16.png" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding EnumInstance}" Value="Three">
                        <Setter Property="Image.Source" Value="/WpfApplication2;component/Images/CloseRed_16.png" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
    <ComboBox ItemsSource="{Binding EnumCollection}" SelectedItem="{Binding EnumInstance}" />
</StackPanel>