Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Can';I don’我不能靠财产来工作_C#_Wpf_Xaml_Attached Properties - Fatal编程技术网

C# Can';I don’我不能靠财产来工作

C# Can';I don’我不能靠财产来工作,c#,wpf,xaml,attached-properties,C#,Wpf,Xaml,Attached Properties,我为WPF文本框编写了一个名为“IsValid”的小附加属性,如下所示: public enum InputTypes { Any, Integer, Double, Float } /// <summary> /// This attached property can be used to validate input for <see cref="TextBox"/>. /// </summary> public

我为WPF文本框编写了一个名为“IsValid”的小附加属性,如下所示:

public enum InputTypes
{
    Any,

    Integer,

    Double,

    Float
}

/// <summary>
/// This attached property can be used to validate input for <see cref="TextBox"/>. 
/// </summary>
public class IsValid : DependencyObject
{
    public static readonly DependencyProperty InputProperty = DependencyProperty.Register(
        "Input",
        typeof(InputTypes),
        typeof(IsValid),
        new UIPropertyMetadata(InputTypes.Any, onInput));

    public static InputTypes GetInput(DependencyObject d)
    {
        return (InputTypes)d.GetValue(InputProperty);
    }

    public static void SetInput(DependencyObject d, InputTypes value)
    {
        d.SetValue(InputProperty, value);
    }

    private static void onInput(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = (TextBox)d;
        var value = (InputTypes)e.NewValue;
        switch (value)
        {
            case InputTypes.Any:
                textBox.PreviewTextInput -= validateInput;
                textBox.PreviewKeyDown -= validateKeyDown;
                break;

            default:
                textBox.PreviewTextInput += validateInput;
                textBox.PreviewKeyDown += validateKeyDown;
                break;
        }
    }

    private static void validateInput(object sender, TextCompositionEventArgs e)
    {
        // enforce numeric input when configured ...
        var textBox = (TextBox) sender;
        var inputTypes = (InputTypes) textBox.GetValue(InputProperty);
        foreach (var c in e.Text)
        {
            switch (inputTypes)
            {
                case InputTypes.Integer:
                    if (!char.IsDigit(c))
                    {
                        e.Handled = true;
                        return;
                    }
                    break;

                case InputTypes.Double:
                case InputTypes.Float:
                    if (!char.IsNumber(c))
                    {
                        e.Handled = true;
                        return;
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }

    private static void validateKeyDown(object sender, KeyEventArgs e)
    {
        // block [SPACE] when numeric input is expected ...
        var textBox = (TextBox)sender;
        var inputTypes = (InputTypes)textBox.GetValue(InputProperty);
        if (inputTypes != InputTypes.Any && e.Key == Key.Space)
            e.Handled = true;
    }
}
公共枚举输入类型
{
任何
整数,
双重的
浮动
}
/// 
///此附加属性可用于验证的输入。
/// 
公共类有效:DependencyObject
{
公共静态只读DependencyProperty InputProperty=DependencyProperty.Register(
“输入”,
类型(输入类型),
类型(IsValid),
新的UIPropertyMetadata(InputTypes.Any,onInput));
公共静态输入类型GetInput(DependencyObject d)
{
返回(InputTypes)d.GetValue(InputProperty);
}
公共静态void SetInput(DependencyObject d,InputTypes值)
{
d、 设置值(InputProperty,value);
}
私有静态void onInput(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
var textBox=(textBox)d;
var值=(输入类型)e.NewValue;
开关(值)
{
案例输入类型。任何:
textBox.previewtdeput-=validateInput;
textBox.PreviewKeyDown-=validateKeyDown;
打破
违约:
textBox.previewtdeput+=validateInput;
textBox.PreviewKeyDown+=validateKeyDown;
打破
}
}
私有静态void validateInput(对象发送方,TextCompositionEventArgs e)
{
//配置时强制数字输入。。。
var textBox=(textBox)发送方;
var inputTypes=(inputTypes)textBox.GetValue(InputProperty);
foreach(e.Text中的var c)
{
开关(输入类型)
{
案例输入类型。整数:
如果(!char.IsDigit(c))
{
e、 已处理=正确;
返回;
}
打破
案例输入类型。双:
案例输入类型。浮动:
如果(!char.IsNumber(c))
{
e、 已处理=正确;
返回;
}
打破
违约:
抛出新ArgumentOutOfRangeException();
}
}
}
私有静态void validateKeyDown(对象发送方,KeyEventArgs e)
{
//当需要数字输入时阻塞[空格]。。。
var textBox=(textBox)发送方;
var inputTypes=(inputTypes)textBox.GetValue(InputProperty);
if(inputTypes!=inputTypes.Any&&e.Key==Key.Space)
e、 已处理=正确;
}
}
下面是我如何使用它的:

<Window x:Class="Spike.Wpf.Controls.TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:values="clr-namespace:Spike.Wpf.Controls.Input;assembly=Spike.Wpf.Controls"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <TextBox values:IsValid.Input="Double" />
</Grid>


但是,在初始化(
DependencyProperty
)之后,
中的任何方法都不会被调用。我遗漏了什么?

之前,您可能遇到一个错误,告诉您,
是有效的
需要从
DependecyObject
派生,因此您添加了这一点,您应该问问自己这是为什么。答案就在这里:

public static readonly DependencyProperty InputProperty = DependencyProperty.Register(...

您尝试为类型
IsValid
上的对象注册一个普通属性,将其更改为
RegisterAttached
,它应该可以工作。(我还将删除继承并使
IsValid
成为一个静态类)

好的,因此问题的核心是微不足道的(请参阅接受的答案):我需要调用
DependencyProperty.Registerated(…)
(与
DependencyProperty.Register(…)相反)

我只是想分享结果。我决定放弃使用简单的
enum
来指定输入类型,而是决定使用标记扩展

附加的属性实现现在如下所示:

public static class IsValid
{
    public static readonly DependencyProperty InputProperty = DependencyProperty.RegisterAttached(
        "Input",
        typeof(IsValidInputExtension),
        typeof(IsValid),
        new UIPropertyMetadata(onInput));

    public static IsValidInputExtension GetInput(DependencyObject d)
    {
        return (IsValidInputExtension)d.GetValue(InputProperty);
    }

    public static void SetInput(DependencyObject d, IsValidInputExtension value)
    {
        d.SetValue(InputProperty, value);
    }

    private static void onInput(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBox = (TextBox)d;
        var value = (IsValidInputExtension)e.NewValue;
        if (value == null)
        {
            textBox.PreviewTextInput -= validateInput;
            textBox.PreviewKeyDown -= validateKeyDown;
            return;
        }
        textBox.PreviewTextInput += validateInput;
        textBox.PreviewKeyDown += validateKeyDown;
    }

    private static void validateInput(object sender, TextCompositionEventArgs e)
    {
        // dispatch validation to specified markup class ...
        var textBox = (TextBox) sender;
        var markup = (IsValidInputExtension)textBox.GetValue(InputProperty);
        markup.ValidateInput(sender, e);
    }

    private static void validateKeyDown(object sender, KeyEventArgs e)
    {
        // dispatch validation to specified markup class ...
        var textBox = (TextBox)sender;
        var markup = (IsValidInputExtension)textBox.GetValue(InputProperty);
        markup.ValidateKeyDown(sender, e);
    }
}
下面是标记扩展类的一部分:

public abstract class IsValidInputExtension : MarkupExtension
{
    internal abstract void ValidateInput(object sender, TextCompositionEventArgs e);
    internal abstract void ValidateKeyDown(object sender, KeyEventArgs e);
}

public class NumericExtension : IsValidInputExtension
{
    public double Minimum { get; set; }

    public double Maximum { get; set; }

    public uint Decimals { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    internal override void ValidateInput(object sender, TextCompositionEventArgs e)
    {
        var textBox = (TextBox) sender;
        if (isDecimalSeparator(e.Text) && Decimals == 0)
        {
            e.Handled = true;
            return;
        }

        // todo: honor Minimum and Maximum ...
    }

    private static bool isDecimalSeparator(string s)
    {
        return CultureInfo.CurrentUICulture.NumberFormat.CurrencyDecimalSeparator == s;
    }

    internal override void ValidateKeyDown(object sender, KeyEventArgs e)
    {
        // block [SPACE] when numeric input is expected ...
        e.Handled = e.Key == Key.Space;
    }
}

public class StringExtension : IsValidInputExtension
{
    public double MaximumLength { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    internal override void ValidateInput(object sender, TextCompositionEventArgs e)
    {
        // (nop)
    }

    internal override void ValidateKeyDown(object sender, KeyEventArgs e)
    {
        // todo: honor MaximumLength here
    }
}
最终的结果,在XAML中,是非常好和容易阅读的

<TextBox v:IsValid.Input="{v:Numeric Minimum=0, Maximum=99, Decimals=0}" />

这一切似乎都如我所愿。谢谢所有的投入

干杯


/Jonas

你能验证属性是否被分配给
输入类型。Double
而不是string
“Double”
?我想再看看你对输入的处理。我认为你的检查没有达到你认为的效果。@Rachel:是的,已经解决了问题(见答案)我可以肯定我确实得到了预期的值。WPF负责解析。@Brent:的确,你完全正确。我也意识到我的解决方案是不够的。只指定“double”或“integer”还不够。我还需要指定允许多少小数以及通常的最小值和最大值。因此,我决定继续构建两个
MarkupExtension
类。生成的语法非常令人愉快。我对WPF非常陌生,但到目前为止,我不得不说它非常强大……Duh!我感觉像个git。谢谢!:O)