无法将MS.Internal.NamedObject类型的对象转换为System.Windows.Datatemplate

时间:2013-11-21 15:11:36

标签: c# wpf

我想根据枚举更改图标。

我为UserControl创建了一个名为CallControlViewModel的新视图模型

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 enum InputTypeEnum
{
    Empty = 0, Number = 1, Text = 2
}

usercontrol背后的代码

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>

当我更改InputType属性时,我在baseViewModel中遇到错误:

PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); ==>
  

InvalidCastException,无法转换类型的对象   MS.Internal.NamedObject到System.Windows.Datatemplate

我做错了什么?

3 个答案:

答案 0 :(得分:5)

是的,整个帖子都是一个凌乱的红色鲱鱼......对于那些不熟悉这种说法的人来说,这意味着你可以忘记所有给出的错误,因为当这样做得好时,你就不会得到那个错误。 ..这是误导性的。

所以我们在这里......使用你的Trigger方法:

首先,这是一个enum

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

现在是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个值,那么最好用它来创建EnumToBoolImageSourceConverterBinding

答案 1 :(得分:2)

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

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

我们在论坛上发布了几个关于此的问题,但从未真正得到答案

答案 2 :(得分:0)

对于遇到相同问题但又找不到其他答案的每个人都有助于发现实际情况。

当您尝试在声明之前使用StaticResource 之前引用资源。

在这个问题上,这些资源是NumberIndicatorTextIndicator

之所以发生这种情况,是因为StaticResource在编译时有效并且无法期待。因此,要解决此问题,您可以将资源移到尚未引用的地方。或只使用运行时DynamicResource