【问题标题】:How can I bind a WPF checkbox's IsChecked property to a boolean property of an object that is not a window如何将 WPF 复选框的 IsChecked 属性绑定到不是窗口的对象的布尔属性
【发布时间】:2016-04-27 21:09:18
【问题描述】:

我找到了很多关于如何将 WPF 复选框的 IsChecked 属性绑定到布尔属性的示例,如果两者都属于同一个 Window 类。我想做不同的事情:

我有主窗口(摘录):

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private readonly SoundFx _soundFx = new SoundFx();

    private void _StartNewGame()
    {
        _soundFx.GameStarted();
    }
}

然后我有 SoundFx 类(摘录):

public class SoundFx : DependencyObject
{
    public void GameStarted()
    {
        if (Enabled)
        {
            _PlayGameStartedSound();
        }
    }

    public bool Enabled
    {
        get { return (bool) GetValue(EnabledProperty); }
        set { SetValue(EnabledProperty, value); }
    }
    public static readonly DependencyProperty EnabledProperty =
        DependencyProperty.Register("Enabled", typeof(bool),
            typeof(SoundFx), new UIPropertyMetadata(false));

}

我有 XAML(摘录):

<Grid>
    <CheckBox IsChecked="{Binding ElementName=_soundFx, Path=Enabled}" x:Name="checkBoxSoundFx" Content="Sound FX" HorizontalAlignment="Right" Margin="0,0,10,10" VerticalAlignment="Bottom"/>
</Grid>

说实话,我是 WPF 的新手,不知道自己在做什么。我想要实现的是,当用户单击checkBoxSoundFx 元素时,_soundFx.Enabled 的值会被更改,而不使用像CheckedUnchecked 这样的任何事件处理程序。这应该可以通过数据绑定来实现,不是吗?

【问题讨论】:

    标签: c# wpf xaml checkbox data-binding


    【解决方案1】:

    首先你需要创建

     public SoundFx _soundFx  { get; set; }
    

    作为公共属性,因为你不能绑定到私有字段

    public MainWindow()
    {
       InitializeComponent();
       _soundFx  = new SoundFx();
    }
    

    而从 xaml 你需要像这样绑定:

    <CheckBox IsChecked=
        "{Binding RelativeSource=
           {RelativeSource Mode=FindAncestor,AncestorType=Window},
           Path=_soundFx.Enabled}"}"
        x:Name="checkBoxSoundFx" 
        Content="Sound FX" 
        HorizontalAlignment="Right" 
        Margin="0,0,10,10" 
        VerticalAlignment="Bottom"/> 
    

    【讨论】:

    • 非常感谢!你介意解释一下为什么会这样吗?我完全无法理解您的 XAML。
    • @Kimmy in xaml,我们找到窗口并绑定到这个窗口属性,你可以阅读RelativeSource,当你的控件的DataContext与你的窗口不同并且你想绑定到窗口时它非常有用属性
    • 哦,伙计,我在一月份还没有经验吗!同时,我当然会决定使用 MVVM 模式来解决这个问题,而不是绑定到有时碰巧在这里有时碰巧在那里的属性。
    【解决方案2】:

    你很接近,你需要一个属性来绑定,如果你没有这样做,你需要设置 DataContext:

    public partial class MainWindow
    {
        public MainWindow()
        {
            this.DataContext = this;
            InitializeComponent();
        }
    
        private readonly SoundFx _soundFx = new SoundFx();
        public SoundFx {get {return _soundFx;}}
    
        private void _StartNewGame()
        {
            _soundFx.GameStarted();
        }
    }
    

    然后你需要绑定到这个属性(如果你只需要设置属性,将模式设置为OneWayToSource,永远不要根据属性值更新CheckBox):

    <Grid>
        <CheckBox IsChecked="{Binding Path=SoundFx.Enabled, Mode=OneWayToSource}" x:Name="checkBoxSoundFx" Content="Sound FX" HorizontalAlignment="Right" Margin="0,0,10,10" VerticalAlignment="Bottom"/>
    </Grid>
    

    顺便说一句,我不确定为什么您的 SoundFx 是 DependencyObject 以及为什么您的 Enabled 属性是 DependencyProperty。在这个特定的示例中,一个简单的属性也可以工作。

    当您想在样式中设置它们或使用情节提要为它们设置动画时,DependencyProperties 很有用,例如,您似乎不在这种情况下。我认为 SoundFx 应该继承 DependencyObject 并且 Enabled 应该是一个简单的属性(虽然这是我对您的项目知之甚少的观点)。

    【讨论】:

      【解决方案3】:

      与此同时,随着我在 WPF 方面的经验越来越丰富,我现在要说我的问题本身是错误的。为了避免视图和模型之间的绑定混淆和不必要的依赖关系,我现在总是更喜欢 MVVM 来处理这种情况。

      示例:https://codereview.stackexchange.com/questions/124361/mvvm-am-i-doing-it-right

      【讨论】:

        猜你喜欢
        • 2012-11-15
        • 1970-01-01
        • 1970-01-01
        • 2012-04-12
        • 2015-03-28
        • 1970-01-01
        • 2020-11-16
        • 1970-01-01
        • 2015-05-19
        相关资源
        最近更新 更多