【问题标题】:How to use Binding like proxy?如何使用像代理一样的绑定?
【发布时间】:2011-09-24 10:03:32
【问题描述】:
<Setter Property="IsChecked">
    <Setter.Value>
        <MultiBinding>
            <!-- Get value for property -->
            <Binding Path="IsPressed" RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
            <!-- Set value to ViewModel's property -->
            <Binding Path="Shift" Mode="OneWayToSource"/>
        </MultiBinding>
    </Setter.Value>
</Setter>

我需要为属性使用 2 个绑定:一个用于获取属性的值,一个用于为 ViewModel 的属性设置值。 我怎样才能实现这种情况?

【问题讨论】:

    标签: wpf binding proxy multibinding


    【解决方案1】:

    您可以创建几个附加属性。一个将是您的绑定目标,第二个将包含您的代理的绑定。例子: 然后在 ProxySource OnChange 实现中,您将获得 TextBox 作为 UIElement,在那里您可以从 ProxySource 读取值并将其写入 ProxyTarget。 这不是一个非常干净的方法,但它应该有效。 如果你不能让它工作,我可以稍后写一个完整的示例。 好的,我已经实现了一切,这里是完整的源代码:

    public class ViewModel : ViewModelBase
    {
        string sourceText;
        public string SourceText
        {
            get { return sourceText; }
            set
            {
                if (sourceText == value) return;
                sourceText = value;
                System.Diagnostics.Debug.WriteLine("SourceText:" + value);
                RaisePropertyChanged("SourceText");
            }
        }
    
        string targetText;
        public string TargetText
        {
            get { return targetText; }
            set
            {
                if (targetText == value) return;
                targetText = value;
                System.Diagnostics.Debug.WriteLine("TargetText:" + value);
                RaisePropertyChanged("TargetText");
            }
        }
    }
    
    public static class AttachedPropertiesHost
    {
        public static object GetProxySource(DependencyObject obj)
        {
            return obj.GetValue(ProxySourceProperty);
        }
    
        public static void SetProxySource(DependencyObject obj, object value)
        {
            obj.SetValue(ProxySourceProperty, value);
        }
    
        public static readonly DependencyProperty ProxySourceProperty =
                DependencyProperty.RegisterAttached(
                    "ProxySource", typeof(object), typeof(AttachedPropertiesHost),
                    new UIPropertyMetadata(null, ProxySourcePropertyPropertyChanged)
                );
    
        private static void ProxySourcePropertyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            dependencyObject.Dispatcher.BeginInvoke(
                    new { Dp = dependencyObject, NewValue = e.NewValue },
                    args => SetProxyTarget(args.Dp, args.NewValue)
                );
        }
    
        public static object GetProxyTarget(DependencyObject obj)
        {
            return obj.GetValue(ProxyTargetProperty);
        }
    
        public static void SetProxyTarget(DependencyObject obj, object value)
        {
            obj.SetValue(ProxyTargetProperty, value);
        }
    
        public static readonly DependencyProperty ProxyTargetProperty =
                DependencyProperty.RegisterAttached("ProxyTarget", typeof(object), typeof(AttachedPropertiesHost));
        }
    
    <TextBox Text="{Binding SourceText, UpdateSourceTrigger=PropertyChanged}" 
                 WpfDataGridLayout:AttachedPropertiesHost.ProxySource="{Binding RelativeSource={RelativeSource Self}, Path=Text, UpdateSourceTrigger=PropertyChanged}"
                 WpfDataGridLayout:AttachedPropertiesHost.ProxyTarget="{Binding TargetText, Mode=OneWayToSource}"
                 />
    

    编辑文本框时控制台的输出: 源文本:f 目标文本:f 源文本:fh 目标文本:fh 源文:fhh 目标文本:fhh

    【讨论】:

      【解决方案2】:

      请不要围绕IsPressed 设计您的解决方案,这实际上是一些人所说的flash 数据,这意味着它会尽快变回默认值(假)。同样上下文Binding 将有专用的目标、源和模式。在MultiBinding 中,不支持以一种方式IsPressed(来自源)和另一种方式保存回另一个Target。要进行双向更新,所有绑定都必须是 TowWay

      尽管对此的 Hack 可能是使用 MultiConverterTarget 本身作为值之一。

           <MultiBinding Converter="MyMultiBindingConverter">
                <!-- Get value for property -->
               <Binding Path="IsPressed"
                        RelativeSource="{RelativeSource Self}" Mode="OneWay"/>
                <!-- Set value to ViewModel's property -->
               <Binding BindsDirectlyToSource="True"/>
           </MultiBinding> 
      
          MyMultiBindingConverter.Convert()
          {
              var myViewModel = values[1] as MyViewModel;
              var isPressed = bool.Parse(values[0].ToString());
              if (isPressed)
              {
                  myViewModel.Shift = !myViewModel.Shift;
              }
          }
      

      但强烈建议这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-28
        • 2012-12-25
        相关资源
        最近更新 更多