Cal.Message.Attach - 找不到方法的目标

时间:2015-04-21 15:09:03

标签: c# wpf xaml caliburn.micro modern-ui

我使用Caliburn.Micro在WPF中设计了一个界面。我已经定制了radiobuttons,它们在被检查时通过cal:Message.Attach属性触发了一个方法。但是当我检查其中一个具有此属性的单选按钮时,我得到以下错误:找不到方法的目标

我的FarKornaView.xaml:

<Grid 
    Style="{StaticResource ContentRoot}"
    x:Class="IKA.Views.FarKornaView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:mui="http://firstfloorsoftware.com/ModernUI"
    xmlns:cal="http://www.caliburnproject.org"
    xmlns:model="clr-namespace:IKA.ViewModels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:ika="clr-namespace:IKA"
    mc:Ignorable="d"
    d:DataContext="{x:Type model:FarKornaViewModel}">
<Grid.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="../Resources/toggle.xaml"></ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
        <ControlTemplate x:Key="RadioButtonStyle" TargetType="ika:RadioButtonExtension">
            <ika:RadioButtonExtension Style="{StaticResource AnimatedSwitch}"  Width="100" Height="40" HorizontalAlignment="Left" Content="{TemplateBinding ContentPresenter.Content}"   GroupName="{TemplateBinding GroupName}" IsChecked="{TemplateBinding IsChecked}" />
        </ControlTemplate>
    </ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*"></ColumnDefinition>
    <ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="Sol Far"  Style="{StaticResource Heading2}"/>
<TextBlock Grid.Column="1" Grid.Row="0" Text="Sağ Far"  Style="{StaticResource Heading2}" />
<TextBlock Grid.Column="0" Grid.Row="3" Text="Toros Farı" Style="{StaticResource Heading2}" />
<TextBlock Grid.Column="1" Grid.Row="3" Text="Angel Eyes"  Style="{StaticResource Heading2}"/>

<ika:RadioButtonExtension x:Name="far_1" Grid.Column="0" Grid.Row="1" GroupName="Sol" Template="{StaticResource RadioButtonStyle}"  Content="Sürekli Yak" />
<ika:RadioButtonExtension x:Name="far_2" Grid.Column="0" Grid.Row="2" GroupName="Sol" Template="{StaticResource RadioButtonStyle}"  Content="Yak Söndür"/>
<ika:RadioButtonExtension x:Name="far_3" Grid.Column="1" Grid.Row="1" GroupName="Sağ" Template="{StaticResource RadioButtonStyle}"  Content="Sürekli Yak"  />
<ika:RadioButtonExtension x:Name="far_4" Grid.Column="1" Grid.Row="2" GroupName="Sağ" Template="{StaticResource RadioButtonStyle}"  Content="Yak Söndür"   />
<ika:RadioButtonExtension x:Name="far_5" Grid.Column="0" Grid.Row="4" GroupName="Toros" Template="{StaticResource RadioButtonStyle}" Content="Sürekli Yak"  cal:Message.Attach="RadioButtonHandler(far_5.GroupName,far_5.Content,far_5.IsChecked)"/>
<ika:RadioButtonExtension x:Name="far_6" Grid.Column="0" Grid.Row="5" GroupName="Toros" Template="{StaticResource RadioButtonStyle}" Content="Yak Söndür"   cal:Message.Attach="RadioButtonHandler(far_6.GroupName,far_6.Content,far_6.IsChecked)"/>
<ika:RadioButtonExtension x:Name="far_7" Grid.Column="1" Grid.Row="4" GroupName="Angel" Template="{StaticResource RadioButtonStyle}" Content="Sürekli Yak"  cal:Message.Attach="RadioButtonHandler(far_7.GroupName,far_7.Content,far_7.IsChecked)"/>
<ika:RadioButtonExtension x:Name="far_8" Grid.Column="1" Grid.Row="5" GroupName="Angel" Template="{StaticResource RadioButtonStyle}" Content="Yak Söndür"   cal:Message.Attach="RadioButtonHandler(far_8.GroupName,far_8.Content,far_8.IsChecked)"/>
</Grid>

我的代码将radiobutton设置为iPhone样式的切换按钮:http://marcangers.com/animated-switch-togglebutton-style-in-wpf/

    <ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:cal="http://www.caliburnproject.org"
  xmlns:ika="clr-namespace:IKA">
    <Style x:Key="AnimatedSwitch" TargetType="{x:Type ika:RadioButtonExtension}">
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="Background" Value="#FAFAFB" />
        <Setter Property="BorderBrush" Value="#EAEAEB" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ika:RadioButtonExtension">
                    <Viewbox Stretch="Uniform">
                        <Canvas Name="Layer_1" Width="100" Height="20" Canvas.Left="10" Canvas.Top="0">
                            <ContentPresenter Canvas.Left="0" Width="70" Height="20" HorizontalAlignment="Left"/>
                            <!--<ContentPresenter Canvas.Left="0" Width="20" Height="20" ContentSource="Content" VerticalAlignment="Center" RecognizesAccessKey="True" />-->
                            <Ellipse  Canvas.Left="80" Width="20" Height="20" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="0.9"/>
                            <Ellipse  Canvas.Left="95" Width="20" Height="20" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="0.9"/>
                            <Border   Canvas.Left="90" Width="15" Height="20" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0.51,0,0.51" />
                            <Ellipse x:Name="ellipse"  Canvas.Left="80" Width="20" Height="20" Fill="White" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="0.3">
                                <Ellipse.RenderTransform>
                                    <TranslateTransform X="0" Y="0" />
                                </Ellipse.RenderTransform>
                                <Ellipse.BitmapEffect>
                                    <DropShadowBitmapEffect Softness="0.1" ShadowDepth="0.7" Direction="270" Color="#BBBBBB"/>
                                </Ellipse.BitmapEffect>
                            </Ellipse>
                        </Canvas>
                    </Viewbox>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True" >
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetProperty="Background.Color" To="#52D468" Duration="0:0:0.2" />
                                        <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#41C955" Duration="0:0:0.2" />
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="0"/>
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value="15" KeySpline="0, 1, 0.6, 1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetProperty="Background.Color" To="#FAFAFB" Duration="0:0:0.2" />
                                        <ColorAnimation Storyboard.TargetProperty="BorderBrush.Color" To="#EAEAEB" Duration="0:0:0.2" />
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Ellipse.RenderTransform).(TranslateTransform.X)" Storyboard.TargetName="ellipse">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="15"/>
                                            <SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0" KeySpline="0, 0.5, 0.5, 1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

我的RadioButtonExtension类使radiobuttons无法检查并获得经典Radiobutton组的功能到这些样式的Radiobuttons:

      public class RadioButtonExtension : RadioButton
  {
    public static int WasChecked { get; set; }

    public bool? IsCheckedChanged
    {
        get
        {
            return (bool?)GetValue(IsCheckedChangedProperty);
        }
        set
        {
            SetValue(IsCheckedChangedProperty, value);
        }
    }

    // Using a DependencyProperty as the backing store for IsChanged.  
   //This enables animation, styling, binding, etc...
  public static readonly DependencyProperty IsCheckedChangedProperty =
        DependencyProperty.Register("IsChanged", typeof(bool?), 
          typeof(RadioButtonExtension),
      new FrameworkPropertyMetadata(false, 
      FrameworkPropertyMetadataOptions.Journal |
      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
        CheckedChanged));

     public static void CheckedChanged(DependencyObject d, 
              DependencyPropertyChangedEventArgs e)
     {
       ((RadioButtonExtension)d).IsChecked = (bool)e.NewValue;
     }

     public RadioButtonExtension()
     {
        this.Click += RadioButtonExtension_Click;
        this.Checked += new RoutedEventHandler(RadioButtonExtension_Checked); 
     }

     void RadioButtonExtension_Click(object sender, System.Windows.RoutedEventArgs e)
     {
         if (WasChecked > 0 && IsCheckedChanged==true)
         {
             this.IsChecked = false;
             WasChecked = 0;

         }
         else if (WasChecked == 0 && IsCheckedChanged == true)
         {
             WasChecked = 1;
         }
     }

    void RadioButtonExtension_Checked(object sender, System.Windows.RoutedEventArgs e)
    {
        if (this.IsChecked == true)
        {
            DependencyObject parent = VisualTreeHelper.GetParent(this);
            DependencyObject parent2 = VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(parent));
            var a = parent2.Ancestors().OfType<RadioButtonExtension>()
                .OrderBy(x => x.GroupName)
                .Where(x => x.GroupName == this.GroupName && x.Name != this.Name)
                .AsEnumerable();
            foreach (RadioButtonExtension button in a)
            {
                button.IsChecked = false;
            }
            IsCheckedChanged = true;
            WasChecked = 0;
        }
        else
        {
            IsCheckedChanged = false;
        }
    }
  }

最后我的FarKornaViewModel包含RadioButtonHandler方法。

 public sealed class FarKornaViewModel : Screen, IMainScreenTabItem
{
    private FarKontrol _farKontrol;
    public FarKornaViewModel(FarKontrol farKontrol)
    {
        _farKontrol = farKontrol;
        DisplayName = "Far Kontrol";
    }
    public void RadioButtonHandler(string groupname, string content, bool isChecked)
    {
        FarDeger.FarIsim = groupname;
        FarDeger.Secim = content;
        FarDeger.isChecked = isChecked;
        _farKontrol.SendCommand();
    }
}

MainView.xaml:

<mui:ModernWindow x:Class="IKA.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:mui="http://firstfloorsoftware.com/ModernUI"
    xmlns:model="clr-namespace:IKA.ViewModels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d"
    d:DataContext="{x:Type model:MainViewModel}"
    Title="{Binding WindowTitle}"
    Height="400" Width="700">
<mui:ModernWindow.MenuLinkGroups>
    <mui:LinkGroup DisplayName="Kontrol" >
        <mui:LinkGroup.Links>
            <mui:Link DisplayName="Far ve Korna Kontrol" Source="..\Views\FarKornaView.xaml"/>
            <mui:Link DisplayName="Bağlantı" Source="..\Views\ConnectionView.xaml"/>
        </mui:LinkGroup.Links>
    </mui:LinkGroup>
    <mui:LinkGroup DisplayName="İKA" >
        <mui:LinkGroup.Links>
            <mui:Link DisplayName="Hakkında" />
            <mui:Link DisplayName="Sistem" />
            </mui:LinkGroup.Links>
        </mui:LinkGroup>
</mui:ModernWindow.MenuLinkGroups>

MainViewModel.cs:

    public class MainViewModel : Screen
{
    private const string WindowTitleDefault = "IKA - Control Panel";
    private string _windowTitle = WindowTitleDefault;
    public MainViewModel()
    {
    }
    public string WindowTitle
    {
        get { return _windowTitle; }
        set
        {
            _windowTitle = value;
            NotifyOfPropertyChange(() => WindowTitle);
        }
    }

编辑1 : 我从RadioButtonExtensions检查了radiobutton的DataContext,我注意到它看起来像MainViewModel,而不是FarKornaViewModel,但我无法弄清楚原因。

编辑2 : 即使我没有设置datacontext,它也会自动设置MainViewModel。有些东西将MainViewModel设置为默认VM,但我不知道是因为Caliburn或Modern.UI或其他原因。

编辑3 : 我发现FarKornaView首先运行是因为MainView中的MenuLinkGroups因此FarKornaViewModel无法运行,所以必须在MainView中显示FarKornaView。我想我应该触发ViewModel而不是链接中的View。

2 个答案:

答案 0 :(得分:1)

指定cal:Action.TargetWithoutContext =“...”以及cal:Message.Attach并确保将其绑定到FarKornaViewModel。发生的事情是Caliburn在附件的目标上使用当前数据上下文(这是错误的视图模型)。如果MainViewModel是数据上下文,那么可以向它添加一个属性以公开你的FarKornaViewModel然后你的目标声明将是cal:Action.TargetWithoutContext =“{Binding FarKornaViewModel}”。

答案 1 :(得分:-2)

我终于解决了这个问题。我创建了一个名为“ViewModelsContainer”的静态类:

    public static class ViewModelsContainer
{
    public static FarKornaViewModel FarKornaViewModel { get; set; }
}

在MainViewModel的构造函数中,将FarKornaViewModel的实例设置为FarKornaViewModel属性。

 public MainViewModel(FarKornaViewModel farKornaViewModel)
        {
            ViewModelsContainer.FarKornaViewModel = farKornaViewModel;
        }

最后在我的FarKornaView.xaml.cs中,我将此属性设置为DataContext。

public FarKornaView()
{
    InitializeComponent();
    this.DataContext = ViewModelsContainer.FarKornaViewModel;
}