[英]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.