2015-04-21 220 views
0

的目标我用Caliburn.Micro在WPF中设计了一个接口。我已经定制了radiobuttons,它们在被检查时通过cal:Message.Attach属性触发了一个方法。但是,当我检查具有这种性质的单选按钮中的一个,我得到的错误:没有目标发现方法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> 

我的代码样式单选按钮作为一个切换按钮像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类,这使得单选按钮uncheckable并获得经典的单选框组的功能,将这些风格的单选按钮:

 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: 我检查了单选按钮的DataContext从RadioButtonExtensions我注意到它的eems作为MainViewModel,而不是FarKornaViewModel,但我不明白为什么。

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

编辑3: 我发现FarKornaView首先运行,因为在的MainView MenuLinkGroups所以FarKornaViewModel不能运行的,在FarKornaView必须进行的MainView表现。我想我应该触发ViewModel而不是从链接查看。

回答

-1

我终于解决了这个问题。我创建了一个名为“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; 
} 
0

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

+0

在我的应用程序中使用modern.UI之前,Caliburn可以检测到正确的ViewModel和正确的目标,但是可能会导致Caliburn的这种误检? –

+0

你错过了设置DataContext的地方吗?在这种情况下,主视图模型会沿着视觉树向下传播。 –

+0

当我将它作为this.DataContext添加到FarKornaView.xaml.cs中时,我只能达到正确的viewmodel,否则即使view.xaml中的datacontext正确或为空,它也会将mainviewmodel作为viewmodel接受。 –