我使用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。
答案 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;
}