【问题标题】:ReadOnlyCheckBox ControlTemplateReadOnlyCheckBox 控件模板
【发布时间】:2010-11-01 07:20:26
【问题描述】:

我一直在尝试创建我的通用 ReadOnlyCheckBox 样式/模板,但我在绑定到数据时遇到了问题。在这里的例子中:

A read-only CheckBox in C# WPF

您直接绑定到 ControlTemplate 定义中的数据,但这当然不是我真正想要的,因为我希望能够像这样声明新的复选框:

        <CheckBox x:Name="uiComboBox" Content="Does not set the backing property, but responds to it."
Style="{StaticResource ReadOnlyCheckBoxStyle}" IsChecked="{Binding MyBoolean}"  Click="uiComboBox_Click"/>

当然,当我这样做然后将项目符号上的事件触发器设置为 IsChecked 的 TemplateBinding 时,我完全拥有我开始的内容!我想我不明白为什么直接在项目符号中设置绑定与设置 IsChecked 然后绑定到它不同,TemplateBinding 不只是引用正在创建的控件的属性中设置的内容的一种方式吗?即使数据没有更新,点击如何触发 UI 更新?是否有 Click I can override 的触发器来停止更新?

我得到了所有 DictionaryResource 的东西工作正常,所以我很高兴,为指针欢呼。

我好奇的另一件事是,如果可以通过在样式中使用 BasedOn 参数来减少我的 Control/Style 模板,那么我只会覆盖我实际需要更改的东西,而不是声明很多东西我认为无论如何都是标准模板的一部分。我可能会玩这个。

干杯

编辑

【问题讨论】:

    标签: c# .net checkbox controltemplate


    【解决方案1】:

    您遇到的问题是您尝试在不应使用的地方使用 DataBinding。

    我不同意您在发布的链接中获得的其他答案。虽然 ControlTemplate 解决方案看起来很整洁,但它们并没有解决您的问题的核心,也就是说,您正在尝试使用单个控件(复选框)来做两件不同的事情:显示状态(例如选中/未选中) 并执行逻辑(远程设备等)。

    ControlTemplates 旨在改变控件出现的方式,而不是行为。你试图改变行为,而不是外表。请参阅“什么是 ControlTemplate?” here了解更多详情

    为此,您将不得不存储一些放弃标准绑定并处理一些事件:

    XAML:

    <Window x:Class="WPFCheckBoxClickTester.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <CheckBox x:Name="foo" Checked="foo_Checked"></CheckBox>
        </Grid>
    </Window>
    

    代码隐藏:

    using System.ComponentModel;
    using System.Threading;
    using System.Windows;
    
    namespace WPFCheckBoxClickTester
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            private BackgroundWorker _worker = new BackgroundWorker();
    
            public Window1()
            {
                InitializeComponent();
    
                foo.IsThreeState = false;
                this._worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
                this._worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
            }
    
            private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                foo.IsChecked = true;
                foo.IsEnabled = true;
                return;
            }
    
            private void _worker_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(500);
                return;
            }
    
            private void foo_Checked(object sender, RoutedEventArgs e)
            {
                if( foo.IsChecked == true && this.foo.IsEnabled )
                {
                    this.foo.IsChecked = false;
                    this.foo.IsEnabled = false;
    
                    this._worker.RunWorkerAsync();
                }
                return;
            }
    
        }
    }
    

    上面的代码示例使您能够通过 BackgroundWorker 异步执行一些代码——我已经放入了 Thread.Sleep 作为占位符。我还在 foo_Checked 中使用 foo.IsEnabled 作为哨兵值,但您可能需要一些额外的状态来处理所有情况(例如,从 Checked 变为 Unchecked)。

    【讨论】:

    • 嗨,Micahtan,感谢您的回复,很抱歉我花了这么长时间才回复您,但我已经进入了一个需要完成的紧急项目。尽管您的答案肯定可以工作,但对我来说并不那么优雅,因为复选框会自行检查,然后在处理选中的事件时我们将其设置回来,如果您在单击时观看按钮,您可以看到检查出现然后再次消失。理想情况下,我希望能够编辑模板以在单击发生时禁用检查,因此它仅在我设置它时发生,或者绑定变量采用新值。干杯编辑
    • 大家好,这个线程上的任何人,我通过创建基于按钮的自定义控件解决了我的问题,请参见此处:stackoverflow.com/questions/1088906/… ed
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多