英文:
WPF Combobox & Textbox Behavior
问题
我做了一个简单的测试,试图分离出我在使用组合框时遇到的问题。我希望在触发计算之前,为用户提供取消对控件所做的编辑的机会。
在测试中,文本框给了我我想要的结果。当取消时,控件恢复为原来的状态。但是,在取消组合框中的输入时,组合框似乎并没有取消。在这两种情况下,模型和视图模型都是正确的。
我如何使组合框的行为与文本框相同,以允许控件正确反映视图模型?
模型和视图模型:
Option Explicit On
Option Strict On
Imports System.ComponentModel
Public Class ViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Public Sub New()
Model = New Model
End Sub
Public Property Model As Model
Public Property Text As String
Get
Return Model.Text
End Get
Set(value As String)
If cancel() Then
OnPropertyChanged("Text")
Exit Property
End If
Model.Text = value
OnPropertyChanged("Text")
End Set
End Property
Private Function cancel() As Boolean
If MsgBox("Cancel?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Return True
Else
Return False
End If
End Function
End Class
Public Class Model
Public Sub New()
Text = "Hello, World!"
End Sub
Public Property Text As String
End Class
视图:
<Window x:Class="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:test"
mc:Ignorable="d"
Title="MainWindow" Height="241" Width="416" d:DataContext="{d:DesignInstance Type=local:ViewModel}">
<Grid>
<TextBox HorizontalAlignment="Left" Margin="108,95,0,0" TextWrapping="Wrap" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
<ComboBox HorizontalAlignment="Left" Margin="108,144,0,0" VerticalAlignment="Top" Width="120" IsEditable="True" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
窗口代码后台:
Class MainWindow
Public Sub New()
InitializeComponent()
DataContext = New ViewModel
End Sub
End Class
英文:
I made a simple test to try and isolate out an issue I was having with comboboxes. I want to give the user the opportunity to cancel the edit made to a control before triggering calculations.
In the test, a textbox gave me the result that I was looking for. When canceling, the control reverts back to what it was. When canceling the input in the combobox, the combobox appears as though it was not canceled. In both of these cases, the model and viewmodel are correct.
How can I have the combobox behave the same way the textbox does to allow the control to reflect the viewmodel correctly?
Model and viewmodel:
Option Explicit On
Option Strict On
Imports System.ComponentModel
Public Class ViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Public Sub New()
Model = New Model
End Sub
Public Property Model As Model
Public Property Text As String
Get
Return Model.Text
End Get
Set(value As String)
If cancel() Then
OnPropertyChanged("Text")
Exit Property
End If
Model.Text = value
OnPropertyChanged("Text")
End Set
End Property
Private Function cancel() As Boolean
If MsgBox("Cancel?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Return True
Else Return False
End If
End Function
End Class
Public Class Model
Public Sub New()
Text = "Hello, World!"
End Sub
Public Property Text As String
End Class
View:
<Window x:Class="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:test"
mc:Ignorable="d"
Title="MainWindow" Height="241" Width="416" d:DataContext="{d:DesignInstance Type=local:ViewModel}">
<Grid>
<TextBox HorizontalAlignment="Left" Margin="108,95,0,0" TextWrapping="Wrap" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
<ComboBox HorizontalAlignment="Left" Margin="108,144,0,0" VerticalAlignment="Top" Width="120" IsEditable="True" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
Window code-behind:
Class MainWindow
Public Sub New()
InitializeComponent()
DataContext = New ViewModel
End Sub
End Class
答案1
得分: 1
因为ComboBox
包含一个TextBox
,当用户执行Cancel()
时,它不会影响TextBox.Text
,这就是为什么会出现这个问题。
我们可以添加一个Button
,在其Click
事件中获取Model
、ComboBox
以及ComboBox
内部的TextBox
的Text
属性。
我正在使用C#,我相信你应该能够理解。
// 在按钮的点击事件中
// 获取ComboBox内部的TextBox
var textBox = cb.Template.FindName("PART_EditableTextBox", cb) as TextBox;
MessageBox.Show($"model: {Model.Text}, cb: {cb.Text}, textBox: {textBox.Text}");
我使用这种方法解决了问题。你可以尝试一下。
<ComboBox x:Name="cb" IsEditable="True" Text="{Binding Path=Text, Delay=5}" />
英文:
Because the ComboBox
contains a TextBox
, when the user Cancel()
, it does not affect the TextBox.Text
, which is why this issue occurs.
We can add a Button
and in its Click
event, obtain the Text
property of the Model
, ComboBox
, and the TextBox
inside the ComboBox
.
I'm using C# and I believe you should be able to understand.
// in Button click event
// get TextBox inside the ComboBox
var textBox = cb.Template.FindName("PART_EditableTextBox", cb) as TextBox;
MessageBox.Show($"model: {Model.Text}, cb: {cb.Text}, textBox: {textBox.Text}");
I solved the problem using this method. You can give it a try.
<ComboBox x:Name="cb" IsEditable="True" Text="{Binding Path=Text, Delay=5}" />
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论