如何将WPF复选框的IsChecked属性绑定到不是窗口的对象的布尔属性

时间:2016-01-21 14:47:39

标签: c# wpf xaml checkbox data-binding

我发现了很多关于如何将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的新手,并不确切知道我在做什么。我想要实现的是,当用户点击_soundFx.Enabled元素时,checkBoxSoundFx的值会被更改,而不会使用CheckedUnchecked等任何事件处理程序。这应该可以通过数据绑定实现,不应该吗?

3 个答案:

答案 0 :(得分:2)

首先你需要创建

 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"/> 

答案 1 :(得分:0)

你很接近,你需要一个属性来绑定,你需要设置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应该是一个简单的属性(这是我对你的项目知之甚少的看法)。

答案 2 :(得分:0)

在此期间,由于我设法在WPF上积累了更多的经验,因此我想说我的问题本身是错误的。为了避免视图和模型之间的绑定混乱和不必要的依赖,在这种情况下,我现在总是更喜欢MVVM。

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