Cal.Message.Attach - 找不到方法的目标
Cal.Message.Attach - No target found for method
我用 Caliburn.Micro 在 WPF 中设计了一个界面。我已经自定义了单选按钮,这些单选按钮在选中时由 cal:Message.Attach 属性 触发。但是当我检查其中一个具有此 属性 的单选按钮时,我得到以下错误:No target found for method
我的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 class,它使单选按钮无法选中,并获得了 classic Radiobutton 组的功能,这些样式的单选按钮:
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 检查了单选按钮的 DataContext
,我注意到它似乎是 MainViewModel,而不是 FarKornaViewModel,但我不明白为什么。
编辑 2:
即使我没有设置数据上下文,它也会自动设置 MainViewModel。有些东西可能将 MainViewModel 设置为默认 VM,但我不知道这是因为 Caliburn 或 Modern.UI 或其他原因。
编辑 3:
我发现FarKornaView 运行首先是因为MainView中的MenuLinkGroups所以FarKornaViewModel不能运行,FarKornaView必须在MainView中显示。我想我应该触发 ViewModel 而不是从链接查看。
指定 cal:Action.TargetWithoutContext="..." 以及 cal:Message.Attach 并确保将其绑定到 FarKornaViewModel。发生的事情是 Caliburn 在附加目标上使用当前数据上下文(这是错误的视图模型)。如果 MainViewModel 是数据上下文,则可以向其添加 属性 以公开您的 FarKornaViewModel,然后您的目标声明将是 cal:Action.TargetWithoutContext="{Binding FarKornaViewModel}"。
我终于解决了这个问题。我创建了一个名为 "ViewModelsContainer" 的静态 class :
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;
}
我用 Caliburn.Micro 在 WPF 中设计了一个界面。我已经自定义了单选按钮,这些单选按钮在选中时由 cal:Message.Attach 属性 触发。但是当我检查其中一个具有此 属性 的单选按钮时,我得到以下错误:No target found for method
我的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 class,它使单选按钮无法选中,并获得了 classic Radiobutton 组的功能,这些样式的单选按钮:
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 检查了单选按钮的 DataContext
,我注意到它似乎是 MainViewModel,而不是 FarKornaViewModel,但我不明白为什么。
编辑 2: 即使我没有设置数据上下文,它也会自动设置 MainViewModel。有些东西可能将 MainViewModel 设置为默认 VM,但我不知道这是因为 Caliburn 或 Modern.UI 或其他原因。
编辑 3: 我发现FarKornaView 运行首先是因为MainView中的MenuLinkGroups所以FarKornaViewModel不能运行,FarKornaView必须在MainView中显示。我想我应该触发 ViewModel 而不是从链接查看。
指定 cal:Action.TargetWithoutContext="..." 以及 cal:Message.Attach 并确保将其绑定到 FarKornaViewModel。发生的事情是 Caliburn 在附加目标上使用当前数据上下文(这是错误的视图模型)。如果 MainViewModel 是数据上下文,则可以向其添加 属性 以公开您的 FarKornaViewModel,然后您的目标声明将是 cal:Action.TargetWithoutContext="{Binding FarKornaViewModel}"。
我终于解决了这个问题。我创建了一个名为 "ViewModelsContainer" 的静态 class :
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;
}