WPF ComboBox 和 TextBox 行为

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

WPF Combobox & Textbox Behavior

问题

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

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

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

WPF ComboBox 和 TextBox 行为

模型和视图模型:

  1. Option Explicit On
  2. Option Strict On
  3. Imports System.ComponentModel
  4. Public Class ViewModel
  5. Implements INotifyPropertyChanged
  6. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
  7. Protected Overridable Sub OnPropertyChanged(propertyName As String)
  8. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
  9. End Sub
  10. Public Sub New()
  11. Model = New Model
  12. End Sub
  13. Public Property Model As Model
  14. Public Property Text As String
  15. Get
  16. Return Model.Text
  17. End Get
  18. Set(value As String)
  19. If cancel() Then
  20. OnPropertyChanged("Text")
  21. Exit Property
  22. End If
  23. Model.Text = value
  24. OnPropertyChanged("Text")
  25. End Set
  26. End Property
  27. Private Function cancel() As Boolean
  28. If MsgBox("Cancel?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
  29. Return True
  30. Else
  31. Return False
  32. End If
  33. End Function
  34. End Class
  35. Public Class Model
  36. Public Sub New()
  37. Text = "Hello, World!"
  38. End Sub
  39. Public Property Text As String
  40. End Class

视图:

  1. <Window x:Class="MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:test"
  7. mc:Ignorable="d"
  8. Title="MainWindow" Height="241" Width="416" d:DataContext="{d:DesignInstance Type=local:ViewModel}">
  9. <Grid>
  10. <TextBox HorizontalAlignment="Left" Margin="108,95,0,0" TextWrapping="Wrap" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
  11. <ComboBox HorizontalAlignment="Left" Margin="108,144,0,0" VerticalAlignment="Top" Width="120" IsEditable="True" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
  12. </Grid>
  13. </Window>

窗口代码后台:

  1. Class MainWindow
  2. Public Sub New()
  3. InitializeComponent()
  4. DataContext = New ViewModel
  5. End Sub
  6. 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:

  1. Option Explicit On
  2. Option Strict On
  3. Imports System.ComponentModel
  4. Public Class ViewModel
  5. Implements INotifyPropertyChanged
  6. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
  7. Protected Overridable Sub OnPropertyChanged(propertyName As String)
  8. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
  9. End Sub
  10. Public Sub New()
  11. Model = New Model
  12. End Sub
  13. Public Property Model As Model
  14. Public Property Text As String
  15. Get
  16. Return Model.Text
  17. End Get
  18. Set(value As String)
  19. If cancel() Then
  20. OnPropertyChanged(&quot;Text&quot;)
  21. Exit Property
  22. End If
  23. Model.Text = value
  24. OnPropertyChanged(&quot;Text&quot;)
  25. End Set
  26. End Property
  27. Private Function cancel() As Boolean
  28. If MsgBox(&quot;Cancel?&quot;, MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
  29. Return True
  30. Else Return False
  31. End If
  32. End Function
  33. End Class
  34. Public Class Model
  35. Public Sub New()
  36. Text = &quot;Hello, World!&quot;
  37. End Sub
  38. Public Property Text As String
  39. End Class

View:

  1. &lt;Window x:Class=&quot;MainWindow&quot;
  2. xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3. xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4. xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
  5. xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
  6. xmlns:local=&quot;clr-namespace:test&quot;
  7. mc:Ignorable=&quot;d&quot;
  8. Title=&quot;MainWindow&quot; Height=&quot;241&quot; Width=&quot;416&quot; d:DataContext=&quot;{d:DesignInstance Type=local:ViewModel}&quot;&gt;
  9. &lt;Grid&gt;
  10. &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;
  11. &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;
  12. &lt;/Grid&gt;
  13. &lt;/Window&gt;

Window code-behind:

  1. Class MainWindow
  2. Public Sub New()
  3. InitializeComponent()
  4. DataContext = New ViewModel
  5. End Sub
  6. End Class

答案1

得分: 1

因为ComboBox包含一个TextBox,当用户执行Cancel()时,它不会影响TextBox.Text,这就是为什么会出现这个问题。

我们可以添加一个Button,在其Click事件中获取ModelComboBox以及ComboBox内部的TextBoxText属性。

我正在使用C#,我相信你应该能够理解。

  1. // 在按钮的点击事件中
  2. // 获取ComboBox内部的TextBox
  3. var textBox = cb.Template.FindName("PART_EditableTextBox", cb) as TextBox;
  4. MessageBox.Show($"model: {Model.Text}, cb: {cb.Text}, textBox: {textBox.Text}");

我使用这种方法解决了问题。你可以尝试一下。

  1. <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.

  1. // in Button click event
  2. // get TextBox inside the ComboBox
  3. var textBox = cb.Template.FindName(&quot;PART_EditableTextBox&quot;, cb) as TextBox;
  4. 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.

  1. &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:

确定