0

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

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 模板,那么我只会覆盖我实际需要更改的内容,而不是声明很多我认为的东西无论如何都是标准模板的一部分。我可能会玩这个。

干杯

4

1 回答 1

0

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

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

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

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

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)。

于 2009-06-08T23:13:58.823 回答