搜了好长时间,找到这一份容易理解的帖子。复制粘贴运行起来效果也达到了,结果发现MainWindow.cs里没法取得RadioButton的状态。又Google搜了一会儿(( ఠൠఠ )ノ面向搜索引擎编程的我),看到别人的MainWindow()构造函数里,有一句var
viewModel =
new
ViewModel();
DataContext = viewModel;
才明白过来,为啥自己要照抄源码,不动脑子。源码XML里设定了DataContext,我删掉后在MainWindow()构造函数里加,不就能得到RadioButton的状态了。如下:
<Window x:Class="WpfApp2demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2demo"
xmlns:local_viewmodel="clr-namespace:ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" Closing="Window_Closing">
<!--
//好傻,不应该在这里指定DataContext的,搞得MainWindow.cs里面不能得到控件的值/
<Window.DataContext>
<local_viewmodel:ViewModelClass/>
</Window.DataContext>
-->
<Window.Resources>
<local_viewmodel:MyConverter x:Key="MyConverter"/>
</Window.Resources>
<Grid>
<StackPanel Width="156" Orientation="Horizontal" Margin="318,131,318,0">
<RadioButton GroupName="name" IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, Converter={StaticResource MyConverter}, ConverterParameter=0}" Content="Option A" Width="45"/>
<RadioButton GroupName="name" IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, Converter={StaticResource MyConverter}, ConverterParameter=1}" Content="Option B" Width="45"/>
<RadioButton GroupName="name" IsChecked="{Binding Path=CurrentOption, Mode=TwoWay, Converter={StaticResource MyConverter}, ConverterParameter=2}" Content="Option C" Width="60"/>
</StackPanel>
<Button Content="Show your selection" Command="{Binding Path=CmdShowMessage}" HorizontalAlignment="Left" Margin="342,62,0,0" VerticalAlignment="Top" Width="128"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ViewModel;
namespace WpfApp2demo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InitUi();
}
ViewModelClass vmc1 = new ViewModelClass();
private void InitUi()
{
//绑定事件/
vmc1.ExchangeEvent += ExchangeRadioBtn;
DataContext = vmc1;
}
private void ExchangeRadioBtn(object sender, RoutedEventArgs e)
{
MessageBox.Show("MainWindow ->RadioBtn:" + vmc1.CurrentOption);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
//ViewModelClass : Window, INotifyPropertyChanged/
//因为ViewModelClass继承了Window(为了传路由事件)所以在关闭窗口的时候需要手动关闭,否则关闭窗口会很慢/
vmc1.Close();
}
}
}
其他源码都的内容完全是搜索引擎复制来的,我在里面加了个路由事件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
namespace ViewModel
{
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//value是radio接到binding變數的值後,來呼叫converter
//converter負責判定接到的值是代表true還是false
if (value == null || parameter == null)
return false;
string checkvalue = value.ToString();
string targetvalue = parameter.ToString();
bool r = checkvalue.Equals(targetvalue,
StringComparison.InvariantCultureIgnoreCase);
return r;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//value 是目前 radiobutton 的 true/false
//在這裡把 parameter 傳回 View-Model
if (value == null || parameter == null)
return null;
bool usevalue = (bool)value;
if (usevalue)
return parameter.ToString();
return null;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
namespace ViewModel
{
public class ViewModelClass : Window, INotifyPropertyChanged
{
#region 事件初始化
public ViewModelClass()
{
cmdShowMessage = new ShowMsgCmdClass(this);
RadioBtn_VMEvent = EventManager.RegisterRoutedEvent("RadioBtn_VMEvent",
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ViewModelClass));
}
public static RoutedEvent RadioBtn_VMEvent;
public event RoutedEventHandler ExchangeEvent
{
add { base.AddHandler(RadioBtn_VMEvent, value); }
remove { base.RemoveHandler(RadioBtn_VMEvent, value); }
}
#endregion
string currentOption;
public string CurrentOption
{
get
{
return currentOption;
}
set
{
if (value != null) //要判斷一下是否為 null,否則選了A,又選B時,最後一個回傳的會是A的值,這樣就抓不到了。
currentOption = value;
}
}
ShowMsgCmdClass cmdShowMessage;
public ShowMsgCmdClass CmdShowMessage
{
get { return cmdShowMessage; }
set { cmdShowMessage = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string prop)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(prop));
}
public void ShowMsg()
{
System.Windows.MessageBox.Show("You Select " + currentOption);
RoutedEventArgs args = new RoutedEventArgs(RadioBtn_VMEvent, this);
//调用元素的RaiseEvent方法(继承自UIElement类),将事件发出去
this.RaiseEvent(args);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace ViewModel
{
public class ShowMsgCmdClass : ICommand
{
ViewModelClass vm;
public ShowMsgCmdClass(ViewModelClass fvm)
{
vm = fvm;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
vm.ShowMsg();
}
}
}