我正在做一些培训项目。它应该将数字转换为不同的字符串。 继承了转换后的Control,并在我的主窗口中使用它。 所以第一个问题是我想基于我传递给OutputFormatProperty的值创建转换器的实例,所以在这种情况下我创建了应该是类型OctalConverter的转换器,但我获得了默认值,为什么呢? 另一件事是我不想通过将它绑定到CurrentValue来改变转换器中的InputValue,它与NotifyPropertyChanged一起使用,但它似乎没有那样工作。
public partial class ConverterDisplay : UserControl {
private const int DEFAULT_INPUT_VALUE = 0;
private readonly ObservableCollection <DisplayField> _displayFields;
private AbstractNumberConverter _converter;
public static readonly DependencyProperty InputValueProperty = DependencyProperty.Register (
"InputValue",
typeof(int),
typeof(ConverterDisplay),
new PropertyMetadata (DEFAULT_INPUT_VALUE));
public static readonly DependencyProperty OutputFormatProperty = DependencyProperty.Register (
"OutputFormat",
typeof(NumberSystems),
typeof(ConverterDisplay),
new FrameworkPropertyMetadata (NumberSystems.Binary));
public int InputValue {
get {
return (int) GetValue (InputValueProperty);
}
set {
SetValue (InputValueProperty, value);
UpdateDisplay ();
}
}
public NumberSystems OutputFormat {
get {
return (NumberSystems) GetValue (OutputFormatProperty);
}
set {
SetValue (OutputFormatProperty, value);
}
}
public ObservableCollection <DisplayField> DisplayFields {
get { return _displayFields; }
}
public ConverterDisplay () {
_displayFields = new ObservableCollection<DisplayField> ();
InitializeComponent ();
CreateConverter ();
}
private void UpdateDisplay () {
var convertedNumberString = _converter.GetString (InputValue);
if (_displayFields.Count > convertedNumberString.Length)
ResetDisplayFields ();
while (_displayFields.Count < convertedNumberString.Length)
AddDisplayField ();
UpdateValues (convertedNumberString);
}
private void UpdateValues (string convertedString) {
if (_displayFields.Count == 0) return;
for (int i = 0; i < _displayFields.Count; i++) {
_displayFields [i].NumberValue = convertedString [i];
}
}
private void AddDisplayField () {
_displayFields.Insert (
0,
new DisplayField ((int)OutputFormat, _displayFields.Count));
}
private void ResetDisplayFields () {
_displayFields.Clear ();
}
private void CreateConverter () {
switch (OutputFormat) {
case NumberSystems.Binary:
_converter = new BinaryConverter ();
break;
case NumberSystems.Octal:
_converter = new OctalConverter ();
break;
case NumberSystems.Hexadecimal:
_converter = new HexadecimalConverter ();
break;
}
}
}
public enum NumberSystems {
Binary = 2,
Octal = 8,
Hexadecimal = 16
}
然后在主窗口中我试图使用该控件
<converters:ConverterDisplay x:Name="octConverter"
InputValue="{Binding ElementName=Window,Path=CurrentValue}"
OutputFormat="Octal"/>
以防万一
public int CurrentValue {
get { return _currentValue; }
set {
if (value == _currentValue)
return;
ValidateNewValue (value);
OnPropertyChanged ();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
}
===========================
编辑#1
我真的不喜欢这个解决方案但我在ConverterDisplay中创建了公共方法来创建转换器,它在MainWindow初始化之后被调用,所以现在转换器是正确的。 另一件事是我如何将我的UpdateDisplay方法绑定到InputValueProperty?我通过验证发现它获得了正确的值,但我无法看到如何在不创建静态内容的情况下运行该方法。
答案 0 :(得分:0)
关于你的第二个问题(将UpdateDisplay
方法绑定到InputValueProperty
:一般来说,在依赖属性的setter中调用任何方法不是最好的主意,因为在使用数据时从不调用此setter绑定以填充依赖项属性的值,如指出at MSDN:
WPF XAML处理器使用属性系统方法进行依赖 加载二进制XAML和处理属性时的属性 依赖属性。这有效地绕过了财产 包装。实现自定义依赖项属性时,必须执行此操作 考虑到这种行为,应该避免放入任何其他代码 除属性系统方法GetValue之外的属性包装器 和SetValue。
相反,创建一个在InputValue
内容发生变化时调用的回调方法,并从那里调用UpdateDisplay
:
public static readonly DependencyProperty InputValueProperty = DependencyProperty.Register (
"InputValue",
typeof(int),
typeof(ConverterDisplay),
new PropertyMetadata (DEFAULT_INPUT_VALUE, InputValueChangedCallback));
private static void InputValueChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var userControl = dependencyObject as ConverterDisplay;
if (userControl != null)
userControl.UpdateDisplay();
}