WPF ComboBox 和 TextBox 行为

huangapple go评论84阅读模式
英文:

WPF Combobox & Textbox Behavior

问题

我做了一个简单的测试,试图分离出我在使用组合框时遇到的问题。我希望在触发计算之前,为用户提供取消对控件所做的编辑的机会。

在测试中,文本框给了我我想要的结果。当取消时,控件恢复为原来的状态。但是,在取消组合框中的输入时,组合框似乎并没有取消。在这两种情况下,模型和视图模型都是正确的。

我如何使组合框的行为与文本框相同,以允许控件正确反映视图模型?

WPF ComboBox 和 TextBox 行为

模型和视图模型:

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?

WPF ComboBox 和 TextBox 行为

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(&quot;Text&quot;)
				Exit Property
			End If
			Model.Text = value
			OnPropertyChanged(&quot;Text&quot;)
		End Set
	End Property

	Private Function cancel() As Boolean
		If MsgBox(&quot;Cancel?&quot;, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
			Return True
		Else Return False
		End If
	End Function
End Class

Public Class Model
	Public Sub New()
		Text = &quot;Hello, World!&quot;
	End Sub
	Public Property Text As String
End Class

View:

&lt;Window x:Class=&quot;MainWindow&quot;
        xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
        xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
        xmlns:local=&quot;clr-namespace:test&quot;
        mc:Ignorable=&quot;d&quot;
        Title=&quot;MainWindow&quot; Height=&quot;241&quot; Width=&quot;416&quot; d:DataContext=&quot;{d:DesignInstance Type=local:ViewModel}&quot;&gt;
	&lt;Grid&gt;
		&lt;TextBox HorizontalAlignment=&quot;Left&quot; Margin=&quot;108,95,0,0&quot; TextWrapping=&quot;Wrap&quot; Text=&quot;{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;120&quot;/&gt;
		&lt;ComboBox HorizontalAlignment=&quot;Left&quot; Margin=&quot;108,144,0,0&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;120&quot; IsEditable=&quot;True&quot; Text=&quot;{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot;/&gt;
	&lt;/Grid&gt;
&lt;/Window&gt;

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事件中获取ModelComboBox以及ComboBox内部的TextBoxText属性。

我正在使用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(&quot;PART_EditableTextBox&quot;, cb) as TextBox;

MessageBox.Show($&quot;model: {Model.Text}, cb: {cb.Text}, textBox: {textBox.Text}&quot;);

I solved the problem using this method. You can give it a try.

&lt;ComboBox x:Name=&quot;cb&quot; IsEditable=&quot;True&quot; Text=&quot;{Binding Path=Text, Delay=5}&quot; /&gt;

huangapple
  • 本文由 发表于 2023年7月28日 04:39:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76783274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定