понедельник, 27 декабря 2021 г.

XAML: Binding -- Привязка данных и контекст данных

Для установки источника или контекста данных в элементах управления WPF предусмотрено свойство DataContext


Правило Binding: 

Для того чтобы связать переменную (переменные), список или коллекцию с формой, нарисованной в XAML -- надо провести связывание через свойство DataContext. 
После того как  через свойство DataContext Вы объявите связь ваших данных(коллекции) и формы XAML, в форме XAML вы сможете Binding  нужные вам данные объявленные в пространстве имен DataContext.
Для того чтобы объявить связь надо использовать x:Name элемента XAML формы.

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

---------------------------
XAML:
---------------------------

<Grid x:Name = "InfoGrid">

    <TextBox Text="{Binding myFilmInfo}"></TextBox>

 </Grid>


-------------------------------
# С код:
-------------------------------

такой код работать не будет так как myInfo это строка, а не объект, чтобы это заработало надо работать с полем объекта 

string myInfo = "Проверка Биндинга";

InfoGrid.DataContext = myInfo;


-------------------------------


-------------------------------
# С код:
-------------------------------

такой код работать будет так как myInfo это строка, а не объект, чтобы это заработало надо работать с полем объекта 

чтобы работать с объектом создадим класс FilmViewModel

 public class FilmViewModel
    {
        public string Name { get; set; }
    }

***

теперь создадим метод нажатия кнопки по которой все прибиндится

private void ButtonBase_OnClick_Test_B(object sender, RoutedEventArgs e)

        {

            var info = new FilmViewModel // создаем info объект класса FilmViewModel

            {

                Name = "Test Test" // свойству Name присвоим значение

            };

            InfoGrid.DataContext = info;  /// все -- биндимся. Ура 

        }

DataContextна самом деле является свойством зависимости. Он указывает на необработанные данные, так что передаваемый нами объект DataContextнаследуется всем его дочерним элементам управления. Я хочу сказать, что если вы определите DataContextдля a Grid, то все элементы, находящиеся внутри, Gridбудут одинаковыми DataContext.

 Для создания привязки применяется элемент Binding и его свойства:

  • ElementName: имя элемента, к которому идет привязка. Если мы говорим о привязке данных, то данное свойство задействуется редко за исключением тех случаев, когда данные определены в виде свойства в определенном элементе управления

  • Path: ссылка на свойство объекта, к которому идет привязка

  • Source: ссылка на источник данных, который не является элементом управления

Свойства элемента Binding помогают установить источник привязки. 

XML
<Grid DataContext="{StaticResource dtItem}">
<TextBox Text="{Binding MyProperty}" />
</Grid>

Здесь, как я определил DataContextдля элемента GridTextBoxвнутренняя часть сетки может ссылаться на свойство, MyPropertyпоскольку dtItemобъект будет автоматически унаследован всем его дочерним элементам. При использовании привязки DataContextэто самая важная часть, которую вы должны использовать.

Члены привязки

Как вы все знаете о расширениях разметки, привязка на самом деле является расширением разметки. Это класс Bindingс небольшим количеством свойств. Давайте обсудим участников, которые находятся в Binding:

  1. Source Источник : свойство источника содержит файл DataSourceПо умолчанию он ссылается DataContextна элемент управления. Если вы поместите свойство Source для Binding, оно примет его вместо исходного DataContext элемента.
  2. ElementName : в случае Bindingс другим ElementElementName берет имя Element определенного в XAML для ссылки на объект. ElementName действует как замена SourceЕсли для привязки не указан путь, она будет использоваться ToString для получения данных из объекта, переданного как источник.
  3. PathПуть : Path определяет фактический путь свойства для получения строковых данных. Если конечный продукт не является a string, он также будет вызывать ToStringдля получения данных.
  4. ModeРежим : определяет, как данные будут передаваться. OneWayозначает, что объект будет обновлен только при обновлении источника, наоборот OneWayToSourceTwoWayопределяет данные, которые будут передаваться в обоих направлениях.
  5. UpdateSourceTrigger : это еще одна важная часть любого BindingОн определяет, когда источник будет обновлен. Значение UpdateSourceTriggerможет быть:
    • PropertyChanged : это значение по умолчанию. В результате всякий раз, когда что-либо обновляется в элементе управления, другой связанный элемент будет отражать то же самое.
    • LostFocus : это означает, что всякий раз, когда свойство теряет фокус, свойство обновляется.
    • Explicit:  Явный : если вы выберете эту опцию, вам необходимо явно указать, когда обновлять Source. Вам необходимо использовать для обновления UpdateSource элемента BindingExpressionуправления.
      C #
      BindingExpression bexp = mytextbox.GetBindingExpression(TextBox.TextProperty);
      bexp.UpdateSource();
      Таким образом, источник обновляется.
  6. Converter:  Конвертер : Converterдает вам интерфейс для размещения объекта, который будет вызываться всякий раз, когда объекты привязки обновляются. Любой объект , который реализует IValueConverterможно использовать вместо ConverterВы можете прочитать об этом в Конвертере в Привязке [ ^ ].
  7. ConverterParameter : используется в дополнение Converterк отправке параметров в Converter.
  8. FallbackValue : определяет значение, которое будет помещено, когда объект Bindingне может вернуть какое-либо значение. По умолчанию он пуст.
  9. StringFormat : форматирование string, указывающее, в Formatкакое место будут следовать данные.
  10. ValidatesOnDataErrors : если указано, DataErrorsбудет проверяться. Вы можете использовать IDataErrorInfoдля запуска своего настраиваемого блока проверки при обновлении объекта данных. Вы можете узнать больше о IDataErrorInfoПроверьте свое приложение с помощью IDataErrorInfo [ ^ ].

Привязка в коде программной части

Подобно тому, что вы могли бы сделать с XAML, вы также можете определить привязку в codeBehind. Для этого нужно использовать:

C #
Binding myBinding = new Binding("DataObject");
 myBinding.Source = myDataObject;
 myTextBlock.SetBinding(TextBlock.TextProperty, myBinding);

Вы также можете указать Bindingсвойства таким образом.

Связывание команд

WPF поддерживает CommandBindingКаждый объект команды, например, Buttonпредоставляет свойство с именем, Commandкоторое принимает объект, реализующий ICommandинтерфейс, и будет выполнять метод Executeвсякий раз, когда запускается команда объекта.

Скажем, вы хотите, чтобы ваша команда выполнялась всякий раз, когда вызывается окно Inputs:

XML
<Window.InputBindings>
        <KeyBinding Command="{Binding CreateNewStudent}" Key="N" Modifiers="Ctrl" />
        <MouseBinding Command="{Binding CreateNewStudent}"
		MouseAction="LeftDoubleClick" />
    </Window.InputBindings>

В приведенном выше коде CreateNewStudentэто свойство, которое предоставляет объект, наследующий ICommandинтерфейс, и Executeметод будет вызываться всякий раз, когда вызывается клавиша Ctrl + N или LeftDoubleClickокна.

Примечание . В VS 2008 InputBindingsпринимаются только Staticобъекты Command. Для этого [ ^ ] есть отчет об ошибке , и он будет исправлен в более поздних выпусках.

Вы можете использовать CommandParameterдля передачи параметров методам, составляющим ICommandинтерфейс.

XML
<Button Content="CreateNew" Command="{Binding CreateNewStudent}" />

Аналогично InputBindings, вы можете использовать Commandс расширением ButtonДля выполнения вам необходимо создать объект, который реализует, ICommandкак показано ниже:

C #
public class CommandBase : ICommand
    {
        private Func<object, bool> _canExecute;
        private Action<object> _executeAction;
        private bool canExecuteCache;

        public CommandBase(Action<object>executeAction, Func<object, bool> canExecute)
        {
            this._executeAction = executeAction;
            this._canExecute = canExecute;
        }

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            bool tempCanExecute = _canExecute(parameter);
            canExecuteCache = tempCanExecute;
            return canExecuteCache;
        }
        private event EventHandler _canExecuteChanged;
        public event EventHandler CanExecuteChanged
        {
            add { this._canExecuteChanged += value; }
            remove { this._canExecuteChanged -= value; }
        }
        protected virtual void OnCanExecuteChanged()
        {
            if (this._canExecuteChanged != null)
                this._canExecuteChanged(this, EventArgs.Empty);
        }
        public void Execute(object parameter)
        {
            _executeAction(parameter);
        }

        #endregion
    }

Я использовал CommandBaseкласс, чтобы объекты выглядели менее неуклюжими. Фактический класс объекта выглядит так:

C #
private CommandBase createNewstudent;
        public CommandBase CreateNewStudent
        {
            get
            {

                this.createNewstudent = this.createNewstudent ??
           new CommandBase(param => this.CreateStudent(), param => this.CanCreateStudent);
                return this.createNewstudent;
            }
        }

        private object CreateStudent()
        {
            this.CurrentStudent = new StudentItem();
            return this.CurrentStudent;
        }

        public bool CanCreateStudent
        {
            get { return true; }
        }

Таким образом, вы можете увидеть createNewCommandпассы CreateStudentвыражение LAMDA , которое вызывается , когда объект обновляется. Это CanCreateStudentсвойство, которое также будет вызываться и основанное на trueили false, WPF разрешит выполнение команды.

unittesting.jpg

PropertyBindingИ CommandBindingдать полный пакет , чтобы отделить логику представления от представительского уровня. Это дает архитектуре возможность разделить всю логику. Microsoft создала всю смесь Expression, используя шаблон MVVM, который отделяет представление от представления ViewModelи, следовательно, дает возможность легко обрабатывать модульное тестирование даже для уровня представления. Мы обсудим эту тему более подробно позже в серии.






Комментариев нет:

Отправить комментарий

Паттерн 'Репозиторий' в ASP.NET

  Последнее обновление: 1.11.2015         Одним из наиболее часто используемых паттернов при работе с данными является паттерн 'Репозито...