在 WPF 中使用 StringFormat 通过多重绑定通知和更新源
Notify and update a source through Multibinding with using StringFormat in WPF
请分析以下代码片段:
<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
文本框文本(目标)值将是 modified/formatted,仅由 A,B,C
提供,但应将更新后的文本通知给 D
通过 binding.Model 如下:
A,B,C
=> [TexBox.Text] => D
问题是当 TxtBox_CommandInfo.Text
发生变化时,C# 端的相应源 D
不会得到通知和更新。
- 没有任何
Converters
如何解决这个问题?
- 我是否错误配置了
Multibinding
设置?
它确实需要 StringFormat
功能,因此在不注入转换的情况下,我们有 StringFormat
的替代方案吗?
我还是一头雾水。不太明白你的意思:
我试图在评论中解释的内容,这里有一个解决方案。
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));
}
}
请分析以下代码片段:
<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
文本框文本(目标)值将是 modified/formatted,仅由 A,B,C
提供,但应将更新后的文本通知给 D
通过 binding.Model 如下:
A,B,C
=> [TexBox.Text] => D
问题是当 TxtBox_CommandInfo.Text
发生变化时,C# 端的相应源 D
不会得到通知和更新。
- 没有任何
Converters
如何解决这个问题? - 我是否错误配置了
Multibinding
设置?
它确实需要 StringFormat
功能,因此在不注入转换的情况下,我们有 StringFormat
的替代方案吗?
我还是一头雾水。不太明白你的意思:
我试图在评论中解释的内容,这里有一个解决方案。
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));
}
}