WPF用户控件未处理

时间:2019-05-11 13:54:27

标签: c# wpf user-controls

简而言之:调用手动处置并将引用设置为null不会从托管窗口处置用户控件实例。

我有一个窗口,可以动态地将用户控件的实例添加/删除到网格面板(窗口)中。当窗口关闭时,所有实例都将被丢弃。但是,就我而言,我需要保持窗口处于活动状态,但需要动态添加/删除用户控件的实例。

我已经附上了ANTS内存配置文件的屏幕快照,该屏幕快照显示了它保持活动状态的层次结构。对我来说,一个互操作调用仍在等待处理/正在引用HwndKeyboardInputProvider。如果我认为是正确的,则不确定如何在我的dispose方法中获取要处理的非托管引用的句柄。

有人可以帮助我为我的用户控件实例实施干净处理吗?

用户控件XAML

<UserControl x:Class="CTWPFControls.CTWPFTextbox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             Name="ctTextBox"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid x:Name="root">
        <TextBox d:LayoutOverrides="Width" Name="textBox1" VerticalAlignment="Bottom" 
                 Text="{Binding ElementName=ctTextBox, Path=BindText}" LostFocus="TextBox_LostFocus" 
                 TextChanged="textBox1_TextChanged" PreviewTextInput="textBox1_PreviewTextInput" 
                 GotFocus="TextBox_GotFocus" SpellCheck.IsEnabled="{Binding ElementName=ctTextBox, Path=EnableSpellCheck}" />
    </Grid>
</UserControl>

背后的代码

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.ComponentModel;

namespace CTWPFControls
{
    /// <summary>
    /// Interaction logic for CTWPFTextbox.xaml
    /// </summary>
    public partial class CTWPFTextbox : UserControl,IDisposable
    {
        public void Dispose()
        {

        textBox1.TextChanged -= textBox1_TextChanged;
        textBox1.PreviewTextInput -= textBox1_PreviewTextInput;
        textBox1.GotFocus -= TextBox_GotFocus;
        textBox1.LostFocus -= TextBox_LostFocus;
        textBox1.KeyDown -= TextBox_OnKeyDown;
        textBox1 = null;
        ctTextBox = null;             

        }
        // Need this for binding in the credit search....or anywhere else for that matter
        public static DependencyProperty TextProperty = DependencyProperty.Register("BindText", typeof(string), typeof(CTWPFTextbox));

        public static DependencyProperty CanEnableSpellCheckProperty = DependencyProperty.Register(
            "EnableSpellCheck", typeof(bool), typeof(CTWPFTextbox));
        public event TextChangedEventHandler TextChanged;

        public bool EnableSpellCheck
        {

            get { return (bool)GetValue(SpellCheck.IsEnabledProperty); }
            set { SetValue(SpellCheck.IsEnabledProperty, value); }
        }

        public string BindText
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public enum EditType { AlphaNumeric, Numeric, Alphabetic, Telephone, NoSymbols, Decimal, Money, Date, IncomeExpText, LookupSearch }

        public string Text
        {
            get { return this.textBox1.Text; }
            set
            {

                string controlText;

                controlText = this.ValidateControlText(value);

                if (this.TextBoxType == EditType.AlphaNumeric || this.TextBoxType == EditType.Alphabetic || this.TextBoxType == EditType.NoSymbols)
                    if (this.AutoFormat)
                        controlText = ValidateAlphaTextBox(controlText);

                if (this.TextBoxType == EditType.Numeric || this.TextBoxType == EditType.IncomeExpText)
                    if (this.AutoFormat)
                        controlText = this.FormatNumeric(controlText);

                this.textBox1.Text = controlText;
            }
        }

        public int MaxLength
        {
            get { return this.textBox1.MaxLength; }
            set { textBox1.MaxLength = value; }
        }

        public bool ReadOnly
        {
            get { return this.textBox1.IsReadOnly; }
            set { this.textBox1.IsReadOnly = value; }
        }

        public TextWrapping TextWrap
        {
            get { return this.textBox1.TextWrapping; }
            set { this.textBox1.TextWrapping = value; }
        }


        [DefaultValue(EditType.AlphaNumeric)]
        public EditType TextBoxType { get; set; }

        [DefaultValue(false)]
        public bool HasDecimals { get; set; }

        [DefaultValue(true)]
        public bool AutoFormat { get; set; }

        public CTWPFTextbox()
        {
            InitializeComponent();
        }

        private string FormatNumeric(string controlText)
        {
            decimal controlValue;
            string returnValue;

            if (controlText == string.Empty)
                return string.Empty;

            if (controlText.IndexOf(".") == 0)
            {
                if (controlText.Length == 1)
                    returnValue = "0";
                else
                    returnValue = string.Format("0{0}", controlText);
            }

            try { controlValue = decimal.Parse(controlText); }
            catch { return controlText; }

            if (!this.HasDecimals)
            {
                System.Globalization.NumberFormatInfo format = (new System.Globalization.CultureInfo("en-gb")).NumberFormat;
                format.NumberDecimalDigits = 0;
                returnValue = controlValue.ToString("n", format);
            }
            else
                returnValue = controlValue.ToString("N");

            return returnValue;
        }

        private static bool IsValidOtherKey(Key key)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
                return true;

            if ((key < Key.D0 && key != Key.Space) || (key > Key.Z && key < Key.NumPad0))
                return true;

            return false;
        }

        private static bool IsValidDecimalKey(TextBox textBox, Key key)
        {
            if (IsValidIntegerKey(textBox, key))
                return true;
            if (key == Key.Decimal)
                return !textBox.Text.Contains(".");

            return false;
        }

        private static bool IsValidIntegerKey(TextBox textBox, Key key)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
                return false;
            if (Key.D0 <= key && key <= Key.D9)
                return true;
            if (Key.NumPad0 <= key && key <= Key.NumPad9)
                return true;
            return false;
        }

        public static string ValidateAlphaTextBox(string controlText)
        {
            int currentPosition = 0;
            string currentWord = string.Empty;
            string returnText = string.Empty;
            char currentCharacter;

            if (controlText == null || controlText.Length == 0)
                return string.Empty;

            while (currentPosition < controlText.Length)
            {
                currentCharacter = controlText[currentPosition];

                if (currentCharacter == '\t' || currentCharacter == '\n' || currentCharacter == ' ')
                {
                    if (currentWord.Length != 0)
                    {
                        currentWord = string.Format("{0}{1}", currentWord.Substring(0, 1).ToUpper(),
                            currentWord.Length == 1 ? string.Empty : currentWord.Substring(1, currentWord.Length - 1).ToLower());
                    }

                    returnText += currentWord + currentCharacter;
                    currentWord = string.Empty;
                }
                else
                    currentWord += currentCharacter;

                currentPosition++;
            }

            if (currentWord.Length != 0)
            {
                currentWord = string.Format("{0}{1}", currentWord.Substring(0, 1).ToUpper(),
                    currentWord.Length == 1 ? string.Empty : currentWord.Substring(1, currentWord.Length - 1).ToLower());

                returnText += currentWord;
            }

            return returnText;
        }

        private string ValidateControlText(string controlText)
        {
            char[] characterArray;
            string textValue = string.Empty;

            if (controlText == null)
                return string.Empty;

            // Allow any text in the alpha numeric control
            if (this.TextBoxType == EditType.AlphaNumeric)
                return controlText.Replace("'", "`");

            // Remove anything after the decimal point for numberic type if decimals are not allowed
            if (this.HasDecimals == false && this.TextBoxType == EditType.Numeric)
            {
                int decimalIndex;

                if ((decimalIndex = controlText.IndexOf(".")) != -1)
                    controlText = controlText.Substring(0, decimalIndex);
            }

            // Retrieve the string as a character array
            characterArray = controlText.ToCharArray();

            // Step through each character validating it
            for (int index = 0; index < characterArray.Length; index++)
            {
                switch (this.TextBoxType)
                {
                    case EditType.Alphabetic:
                        if (this.ValidateAlphabeticInput(characterArray[index]))
                            textValue += characterArray[index];

                        break;

                    case EditType.Numeric:
                        if (this.ValidateNumericInput(characterArray[index]))
                            textValue += characterArray[index];

                        break;

                    case EditType.IncomeExpText:
                        if (this.ValidateNumericInput(characterArray[index]))
                            textValue += characterArray[index];

                        break;

                    case EditType.Telephone:
                        if (this.ValidateNumericInput(characterArray[index]))
                            textValue += characterArray[index];

                        break;

                    case EditType.NoSymbols:
                        if (this.ValidateNoSymbolInput(characterArray[index]))
                            textValue += characterArray[index];

                        break;

                    case EditType.Decimal:
                        if (this.ValidateDecimalInput(characterArray[index]))
                            textValue += characterArray[index];

                        break;
                }
            }

            // Set the control's text
            return textValue;
        }

        private bool ValidateAlphabeticInput(char keyChar)
        {
            char[] validCharacters = new char[] { ' ', '`', ',', '.', '-', '_', '@', '/' };

            // Check if the character is part of the lower case alphabet
            if (keyChar >= 'a' && keyChar <= 'z')
                return true;

            // Check if the character is part of the upper case alphabet
            if (keyChar >= 'A' && keyChar <= 'Z')
                return true;

            // Step through our list of valid characters
            foreach (char validCharacter in validCharacters)
            {
                // If the character is in the list of characters, it is valid
                if (validCharacter == (char)keyChar)
                    return true;
            }

            // The character inputted is not allowed in this mode
            return false;
        }

        private bool ValidateNumericInput(char keyChar)
        {
            // Check if the character is a numeric character
            if (keyChar >= '0' && keyChar <= '9')
                return true;

            if (this.TextBoxType == EditType.Numeric || this.TextBoxType == EditType.Decimal)
            {
                // If the character is a decimal place, ensure it is the only one
                if (keyChar == '.' && this.Text.IndexOf('.') == -1 && this.HasDecimals)
                    return true;
            }

            // Do not allow the character
            return false;
        }

        private bool ValidateDecimalInput(char keyChar)
        {
            // Check if the character is a numeric character
            if (keyChar >= '0' && keyChar <= '9')
                return true;

            // If the character is a decimal place, ensure it is the only one
                if (keyChar == '.')
                    return true;

            // Do not allow the character
            return false;
        }

        private bool ValidateNoSymbolInput(char keyChar)
        {
            // Check if the character is part of the lower case alphabet
            if (keyChar >= 'a' && keyChar <= 'z')
                return true;

            // Check if the character is part of the upper case alphabet
            if (keyChar >= 'A' && keyChar <= 'Z')
                return true;

            // Allow numerical digits
            if (keyChar >= '0' && keyChar <= '9')
                return true;

            // Allow the space character
            if (keyChar == ' ')
                return true;

            // The character inputted is not allowed in this mode
            return false;
        }

        public static bool IsValidAlphaKey(Key key)
        {
            if ((Key.A <= key && key <= Key.Z) || key == Key.Space)
            {
                return true;
            }
            return false;
        }

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (this.textBox1.Text.Length == 0 && (TextBoxType != EditType.Telephone && TextBoxType != EditType.Alphabetic && TextBoxType != EditType.AlphaNumeric && TextBoxType != EditType.IncomeExpText && TextBoxType != EditType.LookupSearch))
            {
                this.textBox1.Text = "0";
                return;
            }

            else if (TextBoxType == EditType.Money)
            {
                double temp = double.Parse(this.textBox1.Text);
                this.textBox1.Text = Math.Round(temp, 2).ToString();
            }

            else if (TextBoxType == EditType.Numeric || TextBoxType == EditType.IncomeExpText)
            {
                this.textBox1.Text = this.FormatNumeric(this.textBox1.Text);
            }

            else if (TextBoxType == EditType.Alphabetic)
            {
                this.textBox1.Text = ValidateAlphaTextBox(this.textBox1.Text);
            }
        }

        private void TextBox_OnKeyDown(object sender, KeyEventArgs e)
        {
            if (IsValidOtherKey(e.Key))
                return;

            if (TextBoxType == EditType.Numeric || TextBoxType == EditType.Telephone || TextBoxType == EditType.IncomeExpText)
                e.Handled = !IsValidIntegerKey(this.textBox1, e.Key);
            else if (TextBoxType == EditType.Decimal || TextBoxType == EditType.Money)
                e.Handled = !IsValidDecimalKey(this.textBox1, e.Key);
            else if (TextBoxType == EditType.Alphabetic)
                e.Handled = !IsValidAlphaKey(e.Key);
        }

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (this.textBox1.Text.Length == 0)
            {
                base.OnGotFocus(e);
                this.textBox1.Focus();
                return;
            }

            if (this.TextBoxType == EditType.Numeric || this.TextBoxType == EditType.IncomeExpText)
                this.textBox1.Text = this.textBox1.Text.Replace(",", string.Empty);

            this.textBox1.SelectionStart = 0;
            this.textBox1.SelectionLength = this.textBox1.Text.Length;

            base.OnGotFocus(e);
            this.textBox1.Focus();
        }

        private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            if (TextBoxType == EditType.Numeric || TextBoxType == EditType.Telephone || TextBoxType == EditType.IncomeExpText)
                e.Handled = IsValidNewIntegerKey(e.Text);
            else if (TextBoxType == EditType.Alphabetic)
                e.Handled = IsValidNewAlphaKey(e.Text);
            else if (TextBoxType == EditType.LookupSearch)
                e.Handled = IsValidLookupKey(e.Text);
        }

        public static bool IsValidNewAlphaKey(string key)
        {
            if (key == " ")
                return false;

            string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-'";

            if (allowedChars.IndexOf(key) >= 0)
                return false;
            else
                return true;
        }

        public static bool IsValidLookupKey(string key)
        {
            string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-'%0123456789";

            if (allowedChars.IndexOf(key) >= 0)
                return false;
            else
                return true;                
        }

        private static bool IsValidNewIntegerKey(string key)
        {
            string allowedChars = "0123456789";

            if (allowedChars.IndexOf(key) >= 0)
                return false;
            else
                return true;
        }

        private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextChangedEventHandler h = TextChanged;
            if (h != null)
                h(this, e);
        }
    }
}

enter image description here

参考:

  1. 如果有帮助,则在MSDN论坛中报告了类似的问题,但是对于HwndKeyboardInputProvider来说,解决方案还不够清楚。我正在标记链接here

0 个答案:

没有答案