繁体   English   中英

数据绑定困难

[英]Difficulties with data-binding

尽管已经阅读了数十个主题,但是数据绑定是一个很难理解的概念。

我希望有一个TextBox,它会在每次在我的代码后面更改字段“状态”时更改其文本,以用于调试。

这是我到目前为止的内容:

public partial class ReviewsControl : UserControl
{
    private Status status = MainControl.AppStatus;
    public string StatusDisplay
    {
        get
        {
            return status.ToString();
        }
    }
}

这是我的看法:

<TextBlock x:Name="StatusBlock" HorizontalAlignment="Left" Margin="10,450,0,0" TextWrapping="Wrap" Text="{Binding StatusDisplay, Source=ReviewsControl, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Height="40" Width="205"/>

上面的代码甚至什么也没有显示,更不用说动态地执行了。 如果我希望XAML在C#代码中检测到更改并相应地更改文本框,该怎么办?

我也很早就遇到了问题。 您的视图(显示给最终用户)并不关心事物的来源或来源,只需知道将在View Model控制器中绑定的内容即可。 要使视图中的内容更新,最常见的方法是绑定并使视图模型包含INotifyPropertyChanged接口。 这样一来,您可以在属性更改时强制引发事件,因为“监听”会自动更新。

简单的类,您可以从:INotify中获取事件,公开的事件以允许注册事件,以及实际引发该事件的方法将其向上传递给正在侦听更改的人员。

public class SomeBaseClass : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;
   public void RaisePropertyChanged(string propertyName)
   {
      if (PropertyChanged != null)
         PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
}

一旦完成,您将通过与getter / setter公开,从而在类中公开属性。 您不绑定到字段。

public string SomeThingYouWantToExpose {get; set; }

而且在您的代码中,无论如何,您都会获取数据,刷新标签,以及进行任何设置和提高属性更改的操作

public void GettingSomeData()
{
   // … doing something to get / prepare / whatever...
   SomeThingYouWantToExpose = "some new label";
   // Now raise which the view bound to this property will updated itself
   RaisePropertyChanged( "SomeThingYouWantToExpose" );
}

现在,在您的视图中,您将绑定到任何视图模型对象,然后再绑定到类的属性。 不知道您是否特别需要x:Name引用,它实际上使该字段成为控件中的一个字段。 在此示例中没有必要,除非您由于此字段而试图在同一显示中绑定其他控件。

<TextBlock Height="40" Width="205"  Margin="10,450,0,0"
   HorizontalAlignment="Left" VerticalAlignment="Top" 
   DataContext="{Binding YourViewModelObjectName}"
   Text="{Binding SomeThingYouWantToExpose}" 
   TextWrapping="Wrap" />

希望您的方案中的这些部分会有意义,并使您在项目中前进。 任何其他澄清,请告诉我。

澄清数据上下文绑定

我在应用程序中实施的方式

MyView -- via the visual declaration... be it a window, grid, complex user control with many controls, whatever...


MyDataModel - a class that is used to query data from whatever data source, such as SQL-Server.


MyView_ViewModel - a custom class that has the INotifyPropertyChanged incorporated and where I expose different properties and other objects I want to expose / make available to the view

因此,在MyData_ViewModel中,我将创建视图并创建视图模型。 创建视图后,我将整个视图的DataContext设置为“ MyView_ViewModel”

public class MyData_ViewModel : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;
   public void RaisePropertyChanged(string propertyName)
   {
      if (PropertyChanged != null)
         PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }

   public void LoadingMyDataAndView()
   {
      // Controller I use to get whatever data I need from ex: SQL
      _myDataModel = new MyDataModel();

      // the view / window / control I want to present to users
      _myView = new MyView();

      // Now, set the data context on the view to THIS ENTIRE OBJECT.
      // Now, anything on THIS class made as public can be have a binding
      // directly to the control in the view.  Since the DataContext is 
      // set here, I can bind to anything at this level or lower that is public.
      _myView.DataContext = this;
   }

   private MyView _myView;
   private MyDataModel _myDataModel;

   // such as example exposed property
   public string SomeThingYouWantToExpose {get; set; }

   public void GettingSomeData()
   {
      var something = _myDataModel.GetSomeData();

      // … doing something to get / prepare / whatever...
      SomeThingYouWantToExpose = "some new label";
      // Now raise which the view bound to this property will updated itself
      RaisePropertyChanged( "SomeThingYouWantToExpose" );
   }
}

希望本示例能够说明各个部分如何结合在一起。 由于设置了整个视图,因此视图不再需要单独的DataContext集,只需要绑定到单独的公共属性即可。

假设TextBlock是UserControl的子元素,即

<TextBlock x:Name="StatusBlock" Text="{Binding StatusDisplay}" ... />

在UserControl的XAML中声明,则Binding的RelativeSource应该设置为父UserControl,如下所示:

<TextBlock Text="{Binding StatusDisplay,
                  RelativeSource={RelativeSource AncestorType=UserControl}}" />

由于StatusDisplay是UserControl的属性,即DependencyObject,因此应将其声明为依赖项属性:

public partial class ReviewsControl : UserControl
{
    public static readonly DependencyProperty StatusDisplayProperty =
        DependencyProperty.Register(
            nameof(StatusDisplay), typeof(string), typeof(ReviewsControl);

    public string StatusDisplay
    {
        get { return (string)GetValue(StatusDisplayProperty); }
        set { SetValue(StatusDisplayProperty, value); }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM