英文:
UWP "form" validation event
问题
我有一个包含基本输入控件的 StackPanel
。有些组合选择是无效的。我想在其中一个输入更改时重新计算“表单”的验证。是否有一种事件可以监听父控件上的,每当子控件上的可观察属性更改时触发的事件?
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<RadioButtons Header="Options:">
<RadioButton Content="Option 1"/>
<RadioButton Content="Option 2"/>
</RadioButtons>
<ToggleSwitch OnContent="On" OffContent="Off"/>
<ComboBox>
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
</ComboBox>
</StackPanel>
英文:
I have a StackPanel
of basic input controls. Some combinations selections are invalid. I would like to recompute the "form"s validation every time one of the inputs change. Is there some kind of event you can listen to on the parent control that will trigger when ever an observable property changes on a child?
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<RadioButtons Header="Options:">
<RadioButton Content="Option 1"/>
<RadioButton Content="Option 2"/>
</RadioButtons>
<ToggleSwitch OnContent="On" OffContent="Off"/>
<ComboBox>
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
</ComboBox>
</StackPanel>
答案1
得分: 1
建议使用数据绑定来监听控件的选择变化。在数据绑定中,使用 Binding.Mode 设置为 TwoWay
的绑定,目标的变化将自动传播到源。
定义一个类,继承自 INotifyPropertyChanged,并在 PropertyChanged 事件中重新计算“表单”的验证。
Page.xaml
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
<controls:RadioButtons Header="选项:" SelectedIndex="{x:Bind selectItems.RadioButtonsIndex, Mode=TwoWay}">
<RadioButton Content="选项 1"/>
<RadioButton Content="选项 2"/>
</controls:RadioButtons>
<ToggleSwitch OnContent="打开" OffContent="关闭" IsOn="{x:Bind selectItems.ToggleSwitchState, Mode=TwoWay}"/>
<ComboBox SelectedIndex="{x:Bind selectItems.ComboBoxSelectIndex, Mode=TwoWay}">
<ComboBoxItem Content="项目 1"/>
<ComboBoxItem Content="项目 2"/>
</ComboBox>
</StackPanel>
</Grid>
Page.xaml.cs
public sealed partial class MainPage : Page
{
public SelectItems selectItems = new SelectItems();
public MainPage()
{
this.InitializeComponent();
selectItems.PropertyChanged += SelectItems_PropertyChanged;
}
private void SelectItems_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (selectItems.RadioButtonsIndex == 1
&& selectItems.ToggleSwitchState == true
&& selectItems.ComboBoxSelectIndex == 1)
{
Debug.WriteLine("无效的组合选择");
}
}
}
public class SelectItems: INotifyPropertyChanged
{
private int _radioButtonsIndex;
private bool _toggleSwitchState;
private int _comboBoxSelectIndex;
public SelectItems()
{
RadioButtonsIndex = 0;
ToggleSwitchState= false;
ComboBoxSelectIndex= 0;
}
public int RadioButtonsIndex
{
get => _radioButtonsIndex;
set
{
_radioButtonsIndex = value;
NotifyPropertyChanged();
}
}
public bool ToggleSwitchState
{
get => _toggleSwitchState;
set
{
_toggleSwitchState = value;
NotifyPropertyChanged();
}
}
public int ComboBoxSelectIndex
{
get => _comboBoxSelectIndex;
set
{
_comboBoxSelectIndex = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
英文:
It is recommended to use Data Binding to listen the selection change of the controls. In Data Binding, use Binding.Mode TwoWay
bindings, changes to the target will automatically propagate to the source.
Define a class which inherits INotifyPropertyChanged, and recompute the "form"s validation in the PropertyChanged event.
Page.xaml
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
<controls:RadioButtons Header="Options:" SelectedIndex="{x:Bind selectItems.RadioButtonsIndex, Mode=TwoWay}">
<RadioButton Content="Option 1"/>
<RadioButton Content="Option 2"/>
</controls:RadioButtons>
<ToggleSwitch OnContent="On" OffContent="Off" IsOn="{x:Bind selectItems.ToggleSwitchState, Mode=TwoWay}"/>
<ComboBox SelectedIndex="{x:Bind selectItems.ComboBoxSelectIndex, Mode=TwoWay}">
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
</ComboBox>
</StackPanel>
</Grid>
Page.xaml.cs
public sealed partial class MainPage : Page
{
public SelectItems selectItems = new SelectItems();
public MainPage()
{
this.InitializeComponent();
selectItems.PropertyChanged += SelectItems_PropertyChanged;
}
private void SelectItems_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (selectItems.RadioButtonsIndex == 1
&& selectItems.ToggleSwitchState == true
&& selectItems.ComboBoxSelectIndex == 1)
{
Debug.WriteLine("Invalid combinations selections");
}
}
}
public class SelectItems: INotifyPropertyChanged
{
private int _radioButtonsIndex;
private bool _toggleSwitchState;
private int _comboBoxSelectIndex;
public SelectItems()
{
RadioButtonsIndex = 0;
ToggleSwitchState= false;
ComboBoxSelectIndex= 0;
}
public int RadioButtonsIndex
{
get => _radioButtonsIndex;
set
{
_radioButtonsIndex = value;
NotifyPropertyChanged();
}
}
public bool ToggleSwitchState
{
get => _toggleSwitchState;
set
{
_toggleSwitchState = value;
NotifyPropertyChanged();
}
}
public int ComboBoxSelectIndex
{
get => _comboBoxSelectIndex;
set
{
_comboBoxSelectIndex = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
答案2
得分: 0
我猜最好的做法是在每个子控件上注册处理程序,它们都引发相同的事件。
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<RadioButtons Header="Options:" SelectionChanged="SelectionChanged">
<RadioButton Content="Option 1"/>
<RadioButton Content="Option 2"/>
</RadioButtons>
<ToggleSwitch x:Name="MyToggle" Toggled="MyToggle_Toggled" OnContent="On" OffContent="Off"/>
<ComboBox SelectionChanged="SelectionChanged">
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
</ComboBox>
</StackPanel>
winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
void winrt::App1::implementation::MainWindow::MyToggle_Toggled(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"[PropertyName]" });
}
void winrt::App1::implementation::MainWindow::SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
{
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"[PropertyName]" });
}
然后你可以监听这个事件。
英文:
I guess the best thing to do is to register handlers on each child control which all raise the same event.
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
<RadioButtons Header="Options:" SelectionChanged="SelectionChanged">
<RadioButton Content="Option 1"/>
<RadioButton Content="Option 2"/>
</RadioButtons>
<ToggleSwitch x:Name="MyToggle" Toggled="MyToggle_Toggled" OnContent="On" OffContent="Off"/>
<ComboBox SelectionChanged="SelectionChanged">
<ComboBoxItem Content="Item 1"/>
<ComboBoxItem Content="Item 2"/>
</ComboBox>
</StackPanel>
winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
void winrt::App1::implementation::MainWindow::MyToggle_Toggled(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"[PropertyName]" });
}
void winrt::App1::implementation::MainWindow::SelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Controls::SelectionChangedEventArgs const& e)
{
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"[PropertyName]" });
}
Then you can listen to this event.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论