簡體   English   中英

更改駐留在ComboBox的ControlTemplate中的TextBox的Tag屬性

[英]Change Tag property of TextBox that resides in ControlTemplate of ComboBox

我想在IsEditable="true"時更改WPF ComboBox內的TextBoxTag屬性。

我試過的

<Style TargetType="{x:Type ComboBox}">
    <Setter Property="TextElement.Tag" Value="MyValue" />
</Style>

上面的代碼似乎無效。

我不想要的:

我不想僅針對單個屬性重新定義ComboBox的ControlTemplate

為什么要更改ComboBox內的TextBoxTag而不是使用ComboBoxTag屬性:為什么我按如下所示使用EnterKeyTraversal類:

EnterKeyTraversal.cs

public class EnterKeyTraversal
{
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        var ue = e.OriginalSource as FrameworkElement;

        DependencyObject dep = ue;

        while (!(dep == null || dep is DataGrid))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        if (!(ue is Button || ue is ListBoxItem || dep is DataGrid))
        {
            if (e.Key == Key.Enter)
            {
                if (!(ue.Tag != null && ue.Tag.ToString() == "IgnoreEnterKeyTraversal"))
                {
                    e.Handled = true;
                    ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                }
            }
        }
    }

    private static void ue_Unloaded(object sender, RoutedEventArgs e)
    {
        var ue = sender as FrameworkElement;
        if (ue == null) return;

        ue.Unloaded -= ue_Unloaded;
        ue.PreviewKeyDown -= ue_PreviewKeyDown;
    }

    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),

        typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged));

    static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ue = d as FrameworkElement;
        if (ue == null) return;

        if ((bool)e.NewValue)
        {
            ue.Unloaded += ue_Unloaded;
            ue.PreviewKeyDown += ue_PreviewKeyDown;
        }
        else
        {
            ue.PreviewKeyDown -= ue_PreviewKeyDown;
        }
    }
}

MainWindow

<Window ....... helpers:EnterKeyTraversal.IsEnabled="True">
    ........
</Window>

在其他頁面上:

<TextBox Tag="IgnoreEnterKeyTraversal" /> <!-- Works Fine -->
<ComboBox Tag="IgnoreEnterKeyTraversal" /><!-- Not Working -->

所以,我想如果我更改ComboBoxTextBoxTag ,就可以停止Enter的遍歷

在深入研究EnterKeyTraversal之后,我找到了解決方案:

這是我的新EnterKeyTraversal.cs

public class EnterKeyTraversal
{
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        var ue = e.OriginalSource as FrameworkElement;

        DependencyObject dep = ue;

        while (!(dep == null || dep is DataGrid))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        DependencyObject combo = ue;

        while (!(combo == null || combo is ComboBox))
        {
            combo = VisualTreeHelper.GetParent(combo);
        }

        if (!(ue is Button || ue is ListBoxItem || dep is DataGrid || (combo is ComboBox && ((ComboBox)combo).Tag.ToString() == "IgnoreEnterKeyTraversal")))
        {
            if (e.Key == Key.Enter)
            {
                if (!(ue.Tag != null && ue.Tag.ToString() == "IgnoreEnterKeyTraversal"))
                {
                    e.Handled = true;
                    ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
                }
            }
        }
    }

    private static void ue_Unloaded(object sender, RoutedEventArgs e)
    {
        var ue = sender as FrameworkElement;
        if (ue == null) return;

        ue.Unloaded -= ue_Unloaded;
        ue.PreviewKeyDown -= ue_PreviewKeyDown;
    }

    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),

        typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged));

    static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ue = d as FrameworkElement;
        if (ue == null) return;

        if ((bool)e.NewValue)
        {
            ue.Unloaded += ue_Unloaded;
            ue.PreviewKeyDown += ue_PreviewKeyDown;
        }
        else
        {
            ue.PreviewKeyDown -= ue_PreviewKeyDown;
        }
    }
}

我在回答您的第一個問題: 我想在IsEditable =“ true”時更改WPF ComboBox內的TextBox的Tag屬性。

由於您嘗試更新在ComboBoxControlTemplate中定義的control's屬性,因此styleBindingTrigger無法正常工作。 所以我用了這個輔助類:

助手類:

    public class ComboBoxBehave
    {

        public static string GetApplyTag(DependencyObject obj)
        {
            return (string)obj.GetValue(ApplyTagProperty);
        }

        public static void SetApplyTag(DependencyObject obj, string value)
        {
            obj.SetValue(ApplyTagProperty, value);
        }

        // Using a DependencyProperty as the backing store for ApplyTag.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ApplyTagProperty =
            DependencyProperty.RegisterAttached("ApplyTag", typeof(string), typeof(ComboBoxBehave), new UIPropertyMetadata(null, ApplyTagChanged));


        private static void ApplyTagChanged(DependencyObject DO, DependencyPropertyChangedEventArgs e)
        {
            var combo = DO as ComboBox;
            if (combo != null)
            {
                combo.Loaded += new RoutedEventHandler(combo_Loaded);
            }
        }

        static void combo_Loaded(object sender, RoutedEventArgs e)
        {
            var combo = sender as ComboBox;
            if (combo != null)
            {
                var text = FindChild<TextBox>(sender as DependencyObject, "PART_EditableTextBox");
                if (text != null)
                {
                    text.Tag = GetApplyTag(combo);
                }
            }
        }

        public static T FindChild<T>(DependencyObject parent, string childName)
  where T : DependencyObject
        {
            // Confirm parent and childName are valid. 
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);

                    // If the child is found, break so we do not overwrite the found child. 
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }
    }

XAML:

 <ComboBox Width="200" Name="cmbBox1" IsEditable="True"  >
        <ComboBox.Style>
            <Style TargetType="ComboBox">
                <Style.Triggers>
                    <Trigger Property="IsEditable" Value="True">
                        <Setter Property="local:ComboBoxBehave.ApplyTag" Value="IgnoreEnterKeyTraversal"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ComboBox.Style>
    </ComboBox>

並將TextBox's Tag設置為IgnoreEnterKeyTraversal ,再加上一些通用代碼,可以將同一類用於不同的控件。

您可以考慮創建自己的ComboBox ,如下所示:

public class ComboBox : System.Windows.Controls.ComboBox
{
    public static readonly DependencyProperty TextBoxTagProperty =
        DependencyProperty.Register("TextBoxTag", typeof(object), typeof(ComboBox), new UIPropertyMetadata(null, new PropertyChangedCallback(OnTextBoxTagChanged)));

    public object TextBoxTag
    {
        get { return (object)GetValue(TextBoxTagProperty); }
        set { SetValue(TextBoxTagProperty, value); }
    }


    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        FrameworkElement frameworkElement = GetTemplateChild("PART_EditableTextBox") as FrameworkElement;
        frameworkElement.Tag = TextBoxTag;
    }

    private static void OnTextBoxTagChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
    {
        ComboBox comboBox = d as ComboBox;
        FrameworkElement frameworkElement = comboBox.GetTemplateChild("PART_EditableTextBox") as FrameworkElement;
        frameworkElement.Tag = args.NewValue;
    }
}

然后在您的XAML中:

<local:ComboBox IsEditable="True" Tag="combobox tag" TextBoxTag="edit textbox tag" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM