【问题标题】:Notify and update a source through Multibinding with using StringFormat in WPF在 WPF 中使用 StringFormat 通过 Multibinding 通知和更新源
【发布时间】:2018-08-03 03:01:38
【问题描述】:

请分析以下代码sn-p:

<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 => [TexBox.Text] => D

问题是当TxtBox_CommandInfo.Text 发生更改时,C# 端的各个源 D 不会得到通知和更新。

  1. 没有任何Converters如何实现这个问题的解决方案?
  2. 我是否错误地配置了Multibinding 设置?

它确实需要StringFormat 功能,因此在不注入转换的情况下,我们有任何替代StringFormat 的方法吗?

【问题讨论】:

  • 为什么虚拟机上的D 属性不只是一个结合A + B + C 的getter?
  • 完全不清楚你想要什么。您的TextboxReadOnly。无法更新。任何修改都必须从 A、B 或 C 完成。正如 slugster 所说的 VM 中的格式 D。 publin string D =&gt; $"{A} {B} {C}"; 问题解决了。
  • @BuddhikaChaturanga 您不能在只读文本框上绑定 TwoWay
  • 也许我不明白你想要什么。您有 3 个属性 A、B 和 C。您希望在 TextBox 中显示对这些属性的任何修改。该 TextBox 必须更新您的第四个属性 D ?我对么 ?如果不是,请修改您的问题并明确您想要什么?也许是一幅画或什么
  • @BuddhikaChaturanga 你完全没有理解我的意思。您不需要绑定即可将字符串组合回属性 - 目标属性可以只包含执行此操作的代码。您正在为非常简单的事情尝试复杂的解决方案。这里有这么多 cmets 的事实表明您需要退后一步重新评估您的代码。

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


【解决方案1】:

我还是一头雾水。不明白你的意思:

我试图在 cmets 中解释的内容,这里有一个解决方案。

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#:(视图模型)

 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

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

<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#(虚拟机):

    private string _d;

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

【讨论】:

  • 感谢您的精彩回复// 非常感谢兄弟。不过有一件事!您通过A,B,C 更新了D,然后绑定到Textbox,但我问的是其他方式,这意味着使用Multibind A, B, C 更新TextBox 并且在Text 已更改之后,然后更新D ..
  • 我想他想避免VM中的属性A,B,C。不知道为什么,
  • 想一想,那里的所有属性......这是清晰的流程,用户更改三个组合框选择然后分别更新A.B,C,瞬间Textbox Text将使用@987654338的MultiBind修改@属性,修改Text之后的一件事D属性必须根据Text值进行更改(文本值不仅包含来自A,B,C的值)。
  • @BuddhikaChaturanga 你的每一条评论都让我更加困惑。你所要求的是不可能的。如果您的 TextBox 是只读的,则无法更新任何属性,您必须从 VM 完成这项工作
  • @FoggyFinder 是的 .. 要求用户不能在那里输入任何文本.. 但我们需要 MVVM 上的 textchanged 场景
猜你喜欢
  • 2013-07-03
  • 2011-09-26
  • 2010-10-26
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多