WPF Databinding CheckBox.IsChecked - PullRequest
       11

WPF Databinding CheckBox.IsChecked

7 голосов
/ 18 июня 2009

Как бы я связал член IsChecked CheckBox с переменной члена в моей форме?

(я понимаю, что могу получить к нему доступ напрямую, но я пытаюсь узнать о привязке данных и WPF)

Ниже моя неудачная попытка заставить это работать.

XAML:

<Window x:Class="MyProject.Form1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Title" Height="386" Width="563" WindowStyle="SingleBorderWindow">
<Grid>
    <CheckBox Name="checkBoxShowPending" 
              TabIndex="2" Margin="0,12,30,0" 
              Checked="checkBoxShowPending_CheckedChanged" 
              Height="17" Width="92" 
              VerticalAlignment="Top" HorizontalAlignment="Right" 
              Content="Show Pending" IsChecked="{Binding ShowPending}">
    </CheckBox>
</Grid>
</Window>

Код:

namespace MyProject
{
    public partial class Form1 : Window
    {
        private ListViewColumnSorter lvwColumnSorter;

        public bool? ShowPending
        {
            get { return this.showPending; }
            set { this.showPending = value; }
        }

        private bool showPending = false;

        private void checkBoxShowPending_CheckedChanged(object sender, EventArgs e)
        {
            //checking showPending.Value here.  It's always false
        }
    }
}

Ответы [ 4 ]

12 голосов
/ 18 июня 2009
<Window ... Name="MyWindow">
  <Grid>
    <CheckBox ... IsChecked="{Binding ElementName=MyWindow, Path=ShowPending}"/>
  </Grid>
</Window>

Обратите внимание, я добавил имя к <Window> и изменил привязку в вашем CheckBox. Вам также потребуется реализовать ShowPending как DependencyProperty, если вы хотите, чтобы он мог обновляться при изменении.

2 голосов
/ 08 октября 2010

Добавление к ответу @ Will: так может выглядеть ваш DependencyProperty (созданный с использованием фрагментов Dr. WPF ):

#region ShowPending

/// <summary>
/// ShowPending Dependency Property
/// </summary>
public static readonly DependencyProperty ShowPendingProperty =
    DependencyProperty.Register("ShowPending", typeof(bool), typeof(MainViewModel),
        new FrameworkPropertyMetadata((bool)false));

/// <summary>
/// Gets or sets the ShowPending property. This dependency property 
/// indicates ....
/// </summary>
public bool ShowPending
{
    get { return (bool)GetValue(ShowPendingProperty); }
    set { SetValue(ShowPendingProperty, value); }
}

#endregion
0 голосов
/ 19 мая 2018

Если у вас есть только один элемент управления, который вы хотите привязать к свойству кода, вы можете указать его как источник в привязке через RelativeSource, например:

<CheckBox ...
IsChecked="{Binding ShowPending, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">

Это может быть конец ответа. Но в целом у вас будет несколько элементов управления и вы захотите привязать их к различным свойствам вашего класса. В этом случае удобнее и удобнее использовать тот факт, что свойство DataContext (которое является исходным объектом по умолчанию для привязки данных) наследуется через иерархию элементов управления, поэтому установка его на верхнем уровне сделает его доступны для всех дочерних элементов управления.

Не существует значения по умолчанию для DataContext, но есть как минимум два способа установить свойство DataContext элемента Window так, чтобы оно указывало на себя:

  • Путем установки DataContext = this в конструкторе code-behind. Это очень просто, но некоторые могут утверждать, что в XAML неясно, куда указывает DataContext.
  • Путем установки DataContext в XAML с использованием DataBinding

Самый простой и, я думаю, самый элегантный способ установить DataContext на уровне Window / UserControl в XAML очень прост; просто добавьте DataContext="{Binding RelativeSource={RelativeSource Self}}" к вашему Window элементу. RelativeSource Self просто означает «привязать непосредственно к объекту», который в данном случае является Window объектом. Отсутствие свойства Path приводит к значению по умолчанию Path, которым является сам исходный объект (т.е. окно).

<Window x:Class="MyProject.Form1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <CheckBox ... 
            IsChecked="{Binding ShowPending}">
        </CheckBox>
    </Grid>
</Window>

Как только вы это сделаете, свойство DataContext для всех дочерних элементов управления станет классом Window, поэтому привязка данных к свойствам в вашем коде будет естественной.

Если по какой-то причине вы не хотите устанавливать DataContext в Окне, но хотите установить его ниже по иерархии управления, то вы можете сделать это, используя механизм FindAncestor. Например. если вы хотите установить его для элемента Grid и всех дочерних элементов Grid:

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
    <CheckBox ...
          IsChecked="{Binding ShowPending}">
    </CheckBox>
</Grid>

Вероятно, стоит отметить, что на данный момент мы достигли возможности привязать элемент управления пользовательского интерфейса к свойству класса code-behind и поддерживать это свойство code-behind в актуальном состоянии. с изменениями в элементе пользовательского интерфейса. Поэтому, если пользователь проверяет CheckBox, свойство ShowPending будет обновлено.

Но довольно часто вы также хотите, чтобы обратное было правдой; изменение свойства источника должно быть отражено в соответствующем изменении элемента управления пользовательского интерфейса. Это можно увидеть, добавив другой элемент управления CheckBox в ваше окно, привязанное к тому же свойству ShowPending. Когда вы нажимаете один флажок, вы, вероятно, надеетесь или ожидаете, что другой флажок будет синхронизирован, но этого не произойдет. Чтобы достичь этого, ваш класс code-behind должен либо (a) реализовать INotifyPropertyChanged, (b) добавить событие ShowPendingChanged или (c) сделать ShowPending a Свойство зависимости, Из 3 я предлагаю реализовать INotifyPropertryChanged в вашем коде позади - самый распространенный механизм.

0 голосов
/ 03 февраля 2016

Вы должны установить режим привязки как TwoWay:

<Checkbox IsChecked="{Binding Path=ShowPending, Mode=TwoWay}"/>
...