【问题标题】:WPF TextBox Text multiple triggersWPF TextBox Text 多个触发器
【发布时间】:2011-09-28 08:32:06
【问题描述】:

我正在为一个人做一个联系人列表。

我有一个ItemsControl,它将DataTemplates 用于不同类型的联系信息。例如。电话号码、电子邮件...等

如果是电话号码,我希望用户有 4 个可以编辑号码的文本框。 4 因为格式(他只能编辑数字,格式是自动生成的):

+43 (2) 112233 - 2

每个部分作为一个文本框。并且我想要一个 主文本框 以该格式编写的整数。这意味着当用户编辑这 4 个文本框之一时,主文本框会实时填充格式化数字。

我让它在后面的代码中工作,但由于我现在使用 DataTemplates,我想在 XAML 中实现这个功能。任何想法如何以正确的格式重新生成主文本框的方式向所有这 4 个文本框添加触发器?

【问题讨论】:

    标签: wpf textbox triggers


    【解决方案1】:

    如果我理解正确,并且您不一定需要在主 TextBox 中编辑电话号码,则可以使用多重绑定来完成此操作。这是一个例子:

    <DataTemplate x:Key="PhoneNumberTemplate">
      <StackPanel Orientation="Horizontal">
        <TextBox Name="tbPN1" />
        <TextBox Name="tbPN2" />
        <TextBox Name="tbPN3" />
        <TextBox Name="tbPN4" />
        <TextBox IsReadOnly="True">
          <TextBox.Text>
            <MultiBinding StringFormat="{}+{0} ({1}) {2} - {3}">
              <Binding Path="Text" ElementName="tbPN1" UpdateSourceTrigger="PropertyChanged" />
              <Binding Path="Text" ElementName="tbPN2" UpdateSourceTrigger="PropertyChanged" />
              <Binding Path="Text" ElementName="tbPN3" UpdateSourceTrigger="PropertyChanged" />
              <Binding Path="Text" ElementName="tbPN4" UpdateSourceTrigger="PropertyChanged" />
            </MultiBinding>
          </TextBox.Text>
        </TextBox>
      </StackPanel>
    </DataTemplate>
    

    每次在其他 4 个文本框之一中按下一个键时,这将更新主文本框

    更新
    为了“更新”数据源,我将执行以下操作:

    让 PhoneNumber 类像这样实现 INotifyPropertyChanged:

    public class PhoneNumber : INotifyPropertyChanged {
    
      public event PropertyChangedEventHandler PropertyChanged;
    
      private void OnPropertyChanged(string propertyName) {
        var handler = PropertyChanged;
        if (handler != null) {
          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
      }
    
      private string m_CountryCode;
      public string CountryCode {
        get { return m_CountryCode; }
        set {
          m_CountryCode = value;
          ComputeFullNumber();
          OnPropertyChanged("CountryCode");
        }
      }
    
      private string m_AreaCode;
      public string AreaCode {
        get { return m_AreaCode; }
        set {
          m_AreaCode = value;
          ComputeFullNumber();
          OnPropertyChanged("AreaCode");
        }
      }
    
      private string m_Number;
      public string Number {
        get { return m_Number; }
        set {
          m_Number = value;
          ComputeFullNumber();
          OnPropertyChanged("Number");
        }
      }
    
      private string m_Suffix;
      public string Suffix {
        get { return m_Suffix; }
        set {
          m_Suffix = value;
          ComputeFullNumber();
          OnPropertyChanged("Suffix");
        }
      }
    
      public string FullNumber { get; private set; }
    
      private void ComputeFullNumber() {
        FullNumber = string.Format("+{0} ({1}) {2} - {3}", m_CountryCode, m_AreaCode, m_Number, m_Suffix);
        OnPropertyChanged("FullNumber");
      }
    
    }
    

    那么你的 DataTemplate 就变成了:

    <DataTemplate x:Key="PhoneNumberTemplate">
      <StackPanel Orientation="Horizontal">
        <TextBox Text="{Binding Path=CountryCode, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Path=AreaCode, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Path=Number, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Path=Suffix, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Text="{Binding Path=FullNumber, Mode=OneWay}" IsReadOnly="True" />
      </StackPanel>
    </DataTemplate>
    

    【讨论】:

    • 好的,太好了,我无法想象如何在指定绑定时反映作为我的 Collection 深处某个 Person 对象的一部分的底层对象 (PhoneNumber) 中的文本更改仅包含其他元素而不包含其他元素:Text="{Binding Path=PhoneNumber,Mode=TwoWay}"
    • 好的,我会尝试这种方式.. 可惜没有 MVVM 我不能直接在 XAML 中做一些事情......
    【解决方案2】:

    您应该能够将每个TextBox 绑定到相同的基础属性,并使用具有智能的转换器提取与该TextBox 相关的电话号码部分。伪代码:

    <TextBox Text="{Binding PhoneNumber, Converter={StaticResource PhoneNumberConverter, ConverterParameter=CountryCode}}"/>
    <TextBox Text="{Binding PhoneNumber, Converter={StaticResource PhoneNumberConverter, ConverterParameter=AreaCode}}"/>
    ...
    

    如果您正在使用 MVVM,请在 PhoneNumberViewModel 中使用单独的属性,而不是使用转换器。

    【讨论】:

    • 好的,但是如果我编辑其中一个文本框怎么办?基础值发生变化,但主 TextBox 的 UI 不会更新。或者?我认为它不会被通知。
    • 要处理通知,请查看 INotifyPropertyChanged 接口:msdn.microsoft.com/en-us/library/…
    • 好的,谢谢.. 我决定为此使用 MVVM.. 因为它更容易进行更改:)
    猜你喜欢
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 2012-05-24
    • 1970-01-01
    • 2020-05-15
    • 2014-08-05
    相关资源
    最近更新 更多