Wpf 多绑定转换回问题
为了解决我在另一个项目中遇到的问题,我创建了以下示例来复制这个问题 其思想是,当用户通过滑块或文本框输入新值时,这些值应通过转换器“转换回”,并更新源。但我似乎没有看到这一点,我认为这是因为InternalRep的属性正在写入,但没有通知InternalRepProperty的bindexpression 解决这个问题的最好办法是什么 我尝试的一种方法是处理sliders ValueChanged事件,但这导致转换器。。。ConvertBack然后ConvertBack然后ConvertBack然后ConvertBack,不知道为什么 当用户更改一个值时,我只需要ConvertBack来更新源代码,而不需要其他任何东西。。这可能吗 文本拆分器XAMLWpf 多绑定转换回问题,wpf,multibinding,imultivalueconverter,Wpf,Multibinding,Imultivalueconverter,为了解决我在另一个项目中遇到的问题,我创建了以下示例来复制这个问题 其思想是,当用户通过滑块或文本框输入新值时,这些值应通过转换器“转换回”,并更新源。但我似乎没有看到这一点,我认为这是因为InternalRep的属性正在写入,但没有通知InternalRepProperty的bindexpression 解决这个问题的最好办法是什么 我尝试的一种方法是处理sliders ValueChanged事件,但这导致转换器。。。ConvertBack然后ConvertBack然后ConvertBack
<ContentControl x:Class="WpfApplication23.TextSplitter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:WpfApplication23"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UniformGrid Columns="3" Rows="2">
<TextBox Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TextSplitter}},
Path=InternalRep.First, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
<TextBox Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TextSplitter}},
Path=InternalRep.Second, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
<TextBox Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TextSplitter}},
Path=InternalRep.Third, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
<Slider Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TextSplitter}},
Path=InternalRep.First, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Maximum="255" />
<Slider Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TextSplitter}},
Path=InternalRep.Second, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Maximum="255" />
<Slider Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TextSplitter}},
Path=InternalRep.Third, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Maximum="255" ValueChanged="OnSliderChnaged" />
</UniformGrid>
</ContentControl>
主窗口XAML
<Window x:Class="WpfApplication23.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication23"
Title="MainWindow" Height="640" Width="800" WindowStartupLocation="CenterScreen">
<StackPanel>
<local:TextSplitter First="{Binding A, Mode=TwoWay}"
Second="{Binding B, Mode=TwoWay}"
Third="{Binding C, Mode=TwoWay}"/>
</StackPanel>
</Window>
您需要在ViewModel中实现INotifyPropertyChanged。
在这里,ViewModel是窗口,因此您必须执行以下操作:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
char m_a = 'a';
public char A
{
get { return m_a; }
set
{
if (value != m_a)
{
m_c = value;
RaisePropertyChanged("A");
}
}
}
char m_B = 'b';
public char B
{
get { return m_B; }
set
{
if (value != m_B)
{
m_c = value;
RaisePropertyChanged("B");
}
}
}
char m_c = 'c';
public char C
{
get { return m_c; }
set
{
if (value != m_c)
{
m_c = value;
RaisePropertyChanged("C");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string _Prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(_Prop));
}
}
DelegateCommand _RecomputeCommand;
public DelegateCommand RecomputeCommand
{
get { return _RecomputeCommand ?? (_RecomputeCommand = new DelegateCommand(Recompute)); }
}
public void Recompute()
{
//Do something with A, B and C.
}
}
编辑:您只需将3个滑块绑定到A、B、C(您需要上述实现),然后根据重新计算的命令执行操作,如下所示:
<StackPanel>
<Slider Value="{Binding A}" Maximum="255">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding RecomputeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
<Slider Value="{Binding B}" Maximum="255">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding RecomputeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
<Slider Value="{Binding C}" Maximum="255">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding RecomputeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
</StackPanel>
当然,这可以根据需要在
ContentControl
中执行。我看不出这对我有什么帮助,问题是这些值一开始没有被写回源代码。转换是单向的,通过将源转换为目标。。但是,当用户更改目标时,源不存在updated@wforl如果你不筹集财产,你如何得到通知?无论何时编写绑定
,路径必须指向PropertyChanged ready属性,否则只能在初始化时检索该值。@baboon。问题不在于正在检索的值。。我真的希望只有在初始化时才能读到。问题是TextSplitterControl没有写回MainWindow.A | MainWindow.B | MainWindow。C@wforl你试过我的解决方案吗?我试过了,但没有解决我的问题。也许我不清楚我在追求什么。当用户与滑块/文本框交互时,我希望主窗口中的属性A、B、C的设置器被调用。如果一开始没有调用setter,您的解决方案将如何更改任何内容?当文本框/滑块中的值正在更改时,不会调用ConvertBack函数。您的onSliderManaged
方法做什么?由于您有双向绑定,ConvertBack
将被调用一次,因此在ValueChanged
事件中第二次调用它将使其运行两次。此外,我仍在试图找出代码隐藏中的多重绑定
,但也有可能使其运行两次。OnSliderManaged方法没有实现,它只是一些实验的结果,整个应用程序如我上面所述。问题是,当用户编辑滑块/文本框时,convertback永远不会被调用,这就是我试图解决的问题/remedy我开始认为存在架构问题。通过让二传手被叫来,你到底想达到什么目的?当绑定到一个变量的一个滑块发生变化时,为什么要调用所有3个setter?你在计算吗?我发布的示例代码就是为了演示我在多绑定中遇到的问题。所有三个设置器都将在convertback中调用,因为这是多转换器的工作方式,不是吗?
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
char m_a = 'a';
public char A
{
get { return m_a; }
set
{
if (value != m_a)
{
m_c = value;
RaisePropertyChanged("A");
}
}
}
char m_B = 'b';
public char B
{
get { return m_B; }
set
{
if (value != m_B)
{
m_c = value;
RaisePropertyChanged("B");
}
}
}
char m_c = 'c';
public char C
{
get { return m_c; }
set
{
if (value != m_c)
{
m_c = value;
RaisePropertyChanged("C");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string _Prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(_Prop));
}
}
DelegateCommand _RecomputeCommand;
public DelegateCommand RecomputeCommand
{
get { return _RecomputeCommand ?? (_RecomputeCommand = new DelegateCommand(Recompute)); }
}
public void Recompute()
{
//Do something with A, B and C.
}
}
<StackPanel>
<Slider Value="{Binding A}" Maximum="255">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding RecomputeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
<Slider Value="{Binding B}" Maximum="255">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding RecomputeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
<Slider Value="{Binding C}" Maximum="255">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding RecomputeCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
</StackPanel>