代码之家  ›  专栏  ›  技术社区  ›  S.N Emond

未释放WPF Usercontrol

  •  0
  • S.N Emond  · 技术社区  · 5 年前

    简而言之:手动调用dispose并将reference设置为null不会从宿主窗口释放用户控件实例。

    我附上了蚂蚁的内存档案截图,显示了它在其中保持生存的层次结构。在我看来,一个互操作调用仍然挂起/引用 HwndKeyboardInputProvider . 如果假设是正确的,那么我不确定如何在dispose方法中获取此非托管引用的句柄以进行dispose。

    有人能帮我实现对我的用户控件实例的清理处理吗?

    <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论坛上也报道过类似的问题,但解决方案在这方面还不够明确 . 我正在标记链接 here
    0 回复  |  直到 5 年前