【问题标题】:Binding DependencyProperty in custom control to ViewModel property将自定义控件中的 DependencyProperty 绑定到 ViewModel 属性
【发布时间】:2016-11-18 08:40:51
【问题描述】:

我在我的跨平台原生 Xamarin 应用程序中使用 MVVMCross。我似乎在将自定义控件中的布尔属性绑定到 ViewModel 中的布尔属性时遇到问题。例如:

我的自定义控件 BarCodeTextBox.cs:

public sealed class BarCodeTextBox : TextBox
{

    public BarCodeTextBox()
    {
        this.DefaultStyleKey = typeof(BarCodeTextBox);
    }

    public bool IsListeningForCodes
    {
        get { return (bool)GetValue(IsListeningForCodesProperty); }
        set {
            SetValue(IsListeningForCodesProperty, value);
            if (value)
            {
                IsReadOnly = true;
                PrefixElement.Visibility = Visibility.Collapsed;
                Window.Current.CoreWindow.CharacterReceived += CoreWindow_CharacterReceived;
            }
            else
            {
                IsReadOnly = false;
                Focus(FocusState.Keyboard);
                PrefixElement.Visibility = Visibility.Visible;
                Window.Current.CoreWindow.CharacterReceived -= CoreWindow_CharacterReceived;
            }

            Text = string.Empty;
        }
    }


    // Using a DependencyProperty as the backing store for IsListening.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsListeningForCodesProperty =
        DependencyProperty.Register("IsListeningForCodes", typeof(bool), typeof(BarCodeTextBox), new PropertyMetadata(false));

页面BoxCloseViewModel.cs的viewmodel:

public class BoxCloseViewModel : ViewModelBase
{        
    private bool m_isManualBoxCodeInput;
    public bool IsManualBoxCodeInput
    {
        get { return m_isManualBoxCodeInput; }
        set { SetProperty(ref m_isManualBoxCodeInput, value); }
    }
}

BoxCloseView.xaml 中的绑定:

<Controls:BarCodeTextBox x:Name="BarCodeInput" Text="{Binding BoxCode, Mode=TwoWay}" IsListeningForCodes="{Binding IsManualBoxCodeInput, Mode=OneWay, Converter={StaticResource BoolToInverseBool}}"/>

当我在 ViewModel 中更改 IsManualBoxCodeInput 的值时,控件中没有任何反应(IsListeningForCodes 不会改变)。我检查的东西:

  • 转换器工作正常(移除它并不能解决问题)。事实上,当 ViewModel 属性发生变化时会调用转换器(我可以调试它)。
  • 当我在页面后面的代码中更改 IsListeningForCodes 的值时,它可以工作(控件显示更改)。
  • 当我对字符串属性执行完全相同的操作时,一切正常。
  • 输出日志中没有绑定错误。
  • PropertyChangedEvent 使用 IsManualBoxCodeInput 属性正确触发。
  • 我意识到,在迁移到 MVVMCross 后,另一个具有布尔属性的控件也发生了同样的事情,该属性以前可以工作。

【问题讨论】:

  • 调试跟踪中是否有任何绑定错误?
  • @dymanoid 感谢您的回复。输出日志中没有绑定错误。
  • 你怎么知道 IsListeningForCodes 属性没有改变?您还没有注册 PropertyChangedCallback,也可能没有“内部”绑定(至少您没有向我们展示)。
  • @Clemens 抱歉,我编辑了 BarCodeTextBox.cs 摘录以显示我在做什么。我正在展示隐藏一些模板元素。但是在调试时,我什至不会停止在 set 方法中。
  • 另请参阅此答案并附上解释:stackoverflow.com/a/28302378/1136211

标签: c# uwp mvvmcross uwp-xaml


【解决方案1】:

绑定不调用DependencyObject 的setter 属性。如果您希望在绑定更改时执行某些代码,您需要将其添加为 PropertyMetadata 的回调。

public bool IsListeningForCodes
{
    get { return (bool)GetValue(IsListeningForCodesProperty); }
    set { SetValue(IsListeningForCodesProperty, value); }
}

public static readonly DependencyProperty IsListeningForCodesProperty =
    DependencyProperty.Register("IsListeningForCodes", typeof(bool), typeof(BarCodeTextBox), 
    new PropertyMetadata(false, OnIsListeningForCodesChanged));

static void OnIsListeningForCodesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var instance = (BarCodeTextBox)d;
    instance.OnIsListeningForCodesChanged();
}

void OnIsListeningForCodesChanged()
{
    if (IsListeningForCodes)
    {
        IsReadOnly = true;
        PrefixElement.Visibility = Visibility.Collapsed;
        Window.Current.CoreWindow.CharacterReceived += CoreWindow_CharacterReceived;
    }
    else
    {
        IsReadOnly = false;
        Focus(FocusState.Keyboard);
        PrefixElement.Visibility = Visibility.Visible;
        Window.Current.CoreWindow.CharacterReceived -= CoreWindow_CharacterReceived;
    }

    Text = string.Empty;
}

【讨论】:

  • 就是这样!我只是假设该属性应该由绑定系统调用。非常感谢。
猜你喜欢
  • 2021-09-22
  • 1970-01-01
  • 2019-07-27
  • 2011-05-11
  • 2021-04-20
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
相关资源
最近更新 更多