使用WPF中的StringFormat通过Multibinding通知和更新源

时间:2018-02-23 04:54:25

标签: c# .net wpf data-binding multibinding

请分析以下代码段:

<TextBox x:Name="TxtBox_CommandInfo"  Style="{DynamicResource MetroTextBox}"
    IsReadOnly="True" Controls:TextBoxHelper.Watermark="This is a textbox" 
    HorizontalAlignment="Left" Margin="0,236,0,0" TextWrapping="Wrap"
    VerticalAlignment="Top" Height="154" Width="780" 
    ScrollViewer.HorizontalScrollBarVisibility="Auto" 
    ScrollViewer.VerticalScrollBarVisibility="Auto">
  <TextBox.Text>
    <MultiBinding StringFormat="{}{0} {1} {2}" NotifyOnTargetUpdated="True">
      <Binding  Path="A" />
      <Binding  Path="B" />
      <Binding  Path="C"/>
      <Binding Path="D" Mode="TwoWay" NotifyOnTargetUpdated="True"
          UpdateSourceTrigger="PropertyChanged"/>
    </MultiBinding>
  </TextBox.Text>
</TextBox>

正如您所看到的那样TxtBox_CommandInfo文本框文本(目标)值将仅由A,B,C修改/格式化,但更新的文本应通过binding.Model通知D。如下:

A,B,C =&gt; [TexBox.Text] =&gt; D

问题是C#方面的相应来源DTxtBox_CommandInfo.Text发生变更时未获得通知和更新。

  1. 没有任何Converters如何解决此问题?
  2. 我是否错误配置了Multibinding设置?
  3. 确实需要StringFormat功能,因此如果没有注入转换,我们是否有StringFormat的替代方案?

1 个答案:

答案 0 :(得分:1)

我仍然感到困惑。不确切地知道你的意思:

我在评论中试图解释,这是一个解决方案。

XAML:

 <Grid>
    <StackPanel>
        <ComboBox ItemsSource="{Binding Path=MyTexts}" SelectedItem="{Binding Path=A}" Margin="10"/>
        <ComboBox ItemsSource="{Binding Path=MyTexts}" SelectedItem="{Binding Path=B}" Margin="10"/>
        <ComboBox ItemsSource="{Binding Path=MyTexts}" SelectedItem="{Binding Path=C}" Margin="10"/>

        <TextBox Height="80" Margin="10" Text="{Binding Path=D, Mode=OneWay}" IsReadOnly="True" AcceptsReturn="True" TextWrapping="Wrap">
        </TextBox>
    </StackPanel>
</Grid>

C#:( ViewModel)

 public class MyViewModel : INotifyPropertyChanged
{
    private string _a;
    private string _b;
    private string _c;

    public string A
    {
        get => _a;
        set
        {
            _a = value;
            OnPropertyChanged(nameof(A));
            OnPropertyChanged(nameof(D));
        }
    }
    public string B
    {
        get => _b;
        set
        {
            _b = value;
            OnPropertyChanged(nameof(B));
            OnPropertyChanged(nameof(D));
        }
    }
    public string C
    {
        get => _c;
        set
        {
            _c = value;
            OnPropertyChanged(nameof(C));
            OnPropertyChanged(nameof(D));
        }
    }
    public string D => $"{A} {B} {C}";

    public List<string> MyTexts { get; }

    public MyViewModel()
    {
        MyTexts = new List<string>() { "FHAKWEFJ AWKEEF AWEKF LAEWKF LAWEF", "AAAAAAAAAAAAAAAAAAAAAA", "BBBBBBBBBBBBBBBBBBBBBBBBB", "EEEEEEEEEEEEEEEEEEEEEEEEE", "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG", "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG" };
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

没有黑客,没有魔法,也没有任何事件。普通MVVM

enter image description here

修改 我想这就是你想要的(只显示对上面代码的修改):

<TextBox Height="80" Margin="10" TextChanged="TextBoxBase_OnTextChanged" IsReadOnly="True" AcceptsReturn="True" TextWrapping="Wrap">
   <TextBox.Text>
                <MultiBinding StringFormat="{}{0} {1} {2}" NotifyOnTargetUpdated="True" Mode="OneWay">
                    <Binding  Path="A" Mode="OneWay"/>
                    <Binding  Path="B"  Mode="OneWay"/>
                    <Binding  Path="C" Mode="OneWay"/>
                </MultiBinding>
            </TextBox.Text>
 </TextBox>

C#:

private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{
    if (this.DataContext is MyViewModel dataContext)
        dataContext.D = ((TextBox) sender).Text;
}

C#(VM):

    private string _d;

    public string D
    {
        get => _d;
        set
        {
            _d = value;
            OnPropertyChanged(nameof(D));
        }
    }