将自定义控件中的 DependencyProperty 绑定到 ViewModel 属性
Binding DependencyProperty in custom control to ViewModel property
我在我的跨平台原生 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));
页面的viewmodel BoxCloseViewModel.cs:
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 的值时,它起作用了(控件显示更改)。
- 当我对字符串 属性 执行完全相同的操作时,一切正常。
- 输出日志中没有绑定错误。
- 使用 IsManualBoxCodeInput 正确触发 PropertyChangedEvent 属性。
- 我意识到同样的事情发生在另一个带有布尔值 属性 的控件上,它曾经可以工作,但在迁移到 MVVMCross 之后不再工作了。
绑定不调用 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;
}
我在我的跨平台原生 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));
页面的viewmodel BoxCloseViewModel.cs:
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 的值时,它起作用了(控件显示更改)。
- 当我对字符串 属性 执行完全相同的操作时,一切正常。
- 输出日志中没有绑定错误。
- 使用 IsManualBoxCodeInput 正确触发 PropertyChangedEvent 属性。
- 我意识到同样的事情发生在另一个带有布尔值 属性 的控件上,它曾经可以工作,但在迁移到 MVVMCross 之后不再工作了。
绑定不调用 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;
}