【问题标题】:Update textbox value based on combox selection in uwp using mvvm使用 mvvm 根据 uwp 中的组合框选择更新文本框值
【发布时间】:2026-01-14 09:35:01
【问题描述】:

我有一个组合框和五个用于添加新客户的文本框的视图。要添加客户,请在我的视图模型中声明属性并将这些属性绑定到所有相应的文本框文本属性,例如,

查看:

<StackPanel>
   <ComboBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomers}" DisplayMemberPath="Name"/>
   <Textbox Text="{Binding Name}"/>
   <Textbox Text="{Binding Age}"/>
   <Textbox Text="{Binding Phone}"/>
   <Textbox Text="{Binding Address}"/>
   <Textbox Text="{Binding Email}"/>
<StackPanel>  

视图模型:

    public class myviewmodel
    {

     private string _name;
     public string Name
     {
         get { return _name;}
         set { _name = value; OnPropertyChanged("Name"); }
     } 
      private string _age;
     public string Age
     {
         get { return _age;}
         set { _age = value; OnPropertyChanged("Age"); }
     } 

    private Customer _selectedCustomer;
    public Customer SelectedCustomer
    {
        get { return _selectedCustomer; }
        set { selectedCustomer = value; OnPropertyChanged("SelectedCustomer"); }
    } 


    }

我会将现有的客户名称加载到组合框。更新现有的 客户详细信息,如果我在组合框中选择客户名称,则选择的客户详细信息 应该绑定在文本框中,以便我可以轻松更新它们。但文本框文本 属性已用于添加新客户。那么如何添加和更新 客户使用相同的文本框??

【问题讨论】:

标签: mvvm uwp


【解决方案1】:

文本框的绑定未设置为 SelectedCustomer。试试这个。

<ComboBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomer}" DisplayMemberPath="Name"/>

<Grid Visibility="{Binding ExistingCustomer, Converter={StaticResource VisibilityConverter}}">
    <Textbox Text="{Binding SelectedCustomer.Name, Mode=TwoWay}"/>
    <Textbox Text="{Binding SelectedCustomer.Age, Mode=TwoWay}}"/>
    <Textbox Text="{Binding SelectedCustomer.Phone, Mode=TwoWay}}"/>
    <Textbox Text="{Binding SelectedCustomer.Address, Mode=TwoWay}}"/>
    <Textbox Text="{Binding SelectedCustomer.Email, Mode=TwoWay}}"/>
</Grid>
<Grid Visibility="{Binding ExistingCustomer, Converter={StaticResource VisibilityConverter}}">
    <Textbox Text="{Binding Customer.Name, Mode=TwoWay}"/>
    <Textbox Text="{Binding Customer.Age, Mode=TwoWay}}"/>
    <Textbox Text="{Binding Customer.Phone, Mode=TwoWay}}"/>
    <Textbox Text="{Binding Customer.Address, Mode=TwoWay}}"/>
    <Textbox Text="{Binding Customer.Email, Mode=TwoWay}}"/>
</Grid>

这是转换器的代码

public class VisibilityConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string culture)
    {
        bool displayControl = (bool)value;

        if (displayControl == true)
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string culture)
    {
        return null;
    }
}

请务必在页面资源中引用转换器所在的命名空间

【讨论】:

  • 您提供了如何根据组合框选择将值绑定到文本框的解决方案。没关系。这就是我的一项任务。另一个是通过那些我需要向数据库添加新值的文本框。那么如何将视图模型中声明的属性绑定到文本框? @Allen Ruflolo
  • 所以您尝试使用相同的文本框来完成两件事对吗?您希望他们从下拉列表中显示所选客户的信息,或者显示将添加到数据库中的新用户的信息。这是正确的吗?
  • 是的..想做这两件事..@Allen Rufolo..我们可以这样做吗?
  • 我已经编辑了我的答案。可能包括一个转换器,它会根据是否选择了客户并将被编辑与将添加的新客户来显示/隐藏网格。
  • 完成。感谢您花时间.. :)
【解决方案2】:

使用Interaction Behaviors可以实现。

首先,Behaviors SDK不是UWP内置的,需要从NuGet单独下载。

您可以使用以下命令进行安装:

Install-Package Microsoft.Xaml.Behaviors.Uwp.Managed

或者只使用 NuGet 包管理器并搜索 Microsoft.Xaml.Behaviors.Uwp.Managed

安装后,您只需将 XAML using 语句添加到页面顶部:

<Page ...
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core" />

如果您总是要从 Combobox SelectedItem 绑定 TextBox,则无需创建另一个属性 SelectedCustomer。除非您打算使用 SelectedCustomer 来完成其他一些代码工作。

以下是在没有SelectedCustomer 属性的情况下如何实现TextBox 文本。

<ComboBox x:Name="comboBox" ItemsSource="{Binding Customers}" DisplayMemberPath="Name" HorizontalAlignment="Stretch" Margin="5,0">
    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="SelectionChanged">
            <core:ChangePropertyAction TargetObject="{Binding ElementName=stkData}" PropertyName="DataContext" Value="{Binding SelectedItem, ElementName=comboBox}"  />
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</ComboBox>

<StackPanel Orientation="Vertical" Grid.Row="1" Margin="5,20" DataContext="{Binding SelectedItem, ElementName=comboBox}">
    <TextBox Text="{Binding Name, Mode=TwoWay}" PlaceholderText="Name" Name="Name"/>
    <TextBox Text="{Binding Age, Mode=TwoWay}" PlaceholderText="Age" Name="Age"/>
    <TextBox Text="{Binding Phone, Mode=TwoWay}" PlaceholderText="Phone" Name="Phone"/>
    <TextBox Text="{Binding Address, Mode=TwoWay}" PlaceholderText="Address" Name="Address"/>
    <TextBox Text="{Binding Email, Mode=TwoWay}" PlaceholderText="Email" Name="Email"/>
</StackPanel>

如果您注意到,我将数据从 comboBox SelectedItem 属性绑定到 StackPanel DataContext,然后将单个属性直接绑定到您的 TextBox 的文本。这将处理您的ComboBox 绑定到TextBox。模式应始终为TwoWay,以便在用户修改现有客户详细信息时更新数据。

现在完成此操作后,当您想要使用当前文本框添加新的客户信息时,您想要清除选择而不更改当前值。下面是我如何添加一个带有交互行为的按钮。

并使用Clicked 操作清除TextBox 文本。在 UWP XAML 中,您可以使用空字符串作为值,它可以按预期工作。

<Button Content="+" Grid.Column="1" Margin="5,0" Tag="{Binding EmptyClass, Mode=TwoWay}" Name="btnNew">
    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="Click">
            <core:ChangePropertyAction TargetObject="{Binding ElementName=stkData}" PropertyName="DataContext" Value="{Binding Tag, ElementName=btnNew, Mode=TwoWay}"  />
            <core:ChangePropertyAction TargetObject="{Binding ElementName=comboBox}" PropertyName="SelectedIndex" Value="-1"  />
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</Button>

另请注意,我将ComboBox 的选定索引设置为-1,以便无法更新选定的数据。

现在保存部分应该非常简单直接。下面是我与TappedEvent一起使用的按钮

private void saveBtn_Tapped(object sender, TappedRoutedEventArgs e)
{
    model.Customers.Add(model.EmptyClass);
    model.EmptyClass = new MyClass();
}

您可以看到我正在重新实例化EmptyClass,以便可以清除旧的绑定数据。

下面是完整的 XAML

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App15"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Text="using:System.Text"
    x:Class="App15.MainPage"
    xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"
    Loaded="Page_Loaded"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid Margin="0,100,0,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <ComboBox x:Name="comboBox" ItemsSource="{Binding Customers}" DisplayMemberPath="Name" HorizontalAlignment="Stretch" Margin="5,0">
                    <interactivity:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="SelectionChanged">
                            <core:ChangePropertyAction TargetObject="{Binding ElementName=stkData}" PropertyName="DataContext" Value="{Binding SelectedItem, ElementName=comboBox}"  />
                        </core:EventTriggerBehavior>
                    </interactivity:Interaction.Behaviors>
                </ComboBox>
                <Button Content="+" Grid.Column="1" Margin="5,0" Tag="{Binding EmptyClass, Mode=TwoWay}" Name="btnNew">
                    <interactivity:Interaction.Behaviors>
                        <core:EventTriggerBehavior EventName="Click">
                            <core:ChangePropertyAction TargetObject="{Binding ElementName=stkData}" PropertyName="DataContext" Value="{Binding Tag, ElementName=btnNew, Mode=TwoWay}"  />
                            <core:ChangePropertyAction TargetObject="{Binding ElementName=comboBox}" PropertyName="SelectedIndex" Value="-1"  />
                        </core:EventTriggerBehavior>
                    </interactivity:Interaction.Behaviors>
                </Button>
            </Grid>
            <StackPanel Orientation="Vertical" Grid.Row="1" Margin="5,20" Name="stkData">
                <TextBox Text="{Binding Name, Mode=TwoWay}" PlaceholderText="Name"/>
                <TextBox Text="{Binding Age, Mode=TwoWay}" PlaceholderText="Age" />
                <TextBox Text="{Binding Phone, Mode=TwoWay}" PlaceholderText="Phone" />
                <TextBox Text="{Binding Address, Mode=TwoWay}" PlaceholderText="Address" />
                <TextBox Text="{Binding Email, Mode=TwoWay}" PlaceholderText="Email" />
            </StackPanel>
            <Button Name="saveBtn" Content="Save" HorizontalAlignment="Stretch" Margin="5" Grid.Column="1" Grid.Row="2" Tapped="saveBtn_Tapped"/>
        </Grid>
    </Grid>
</Page>

下面是完整的代码

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;

namespace App15
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        MyViewModel model = new MyViewModel();
        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = model;
        }

        private void saveBtn_Tapped(object sender, TappedRoutedEventArgs e)
        {
            model.Customers.Add(model.EmptyClass);
            model.EmptyClass = new MyClass();
        }
    }
}

下面是完整的视图模型

public class MyViewModel
{
    public MyViewModel()
    {
        Customers = new ObservableCollection<MyClass>();
        EmptyClass = new MyClass();
        for (int i = 0; i < 10; i++)
        {
            Customers.Add(new MyClass()
            {
                Name = "Item" + (i + 1).ToString(),
                Address = "Address" + (i + 1).ToString(),
                Age = "20" + (i + 1).ToString(),
                Email = "Test" + (i + 1).ToString() + "@test.com",
                Phone = (9876543210 + i).ToString()
            });
        }
    }
    public ObservableCollection<MyClass> Customers { get; set; }
    public MyClass EmptyClass { get; set; }
}

public class MyClass
{
    public string Name { get; set; }
    public string Age { get; set; }
    public string Phone { get; set; }
    public string Address { get; set; }
    public string Email { get; set; }
}

我知道甚至可以在 MVVM 中使用 Save Option 但我没有机会使用 DelegateCommand。但是,如果您想自己尝试一下,请查看此Video by Jerry Nixon 以供参考

【讨论】:

  • 其实感谢您花时间。但不幸的是,如果我通过文本框添加新数据,那么添加的名称在组合框中不可见?还有一件事,我想遵循 mvvm 模式,所以如果我通过文本框添加新数据,我应该如何将数据从视图传递到视图模型? (知道通过绑定它是可能的。但是文本框的“文本”属性已经用于显示组合框选定的项目。那我该怎么办??@AVK Naidu