数据绑定是一个困难的概念,尽管已经阅读了数十个主题,但我仍然不太了解。
我希望有一个TextBox,它在每次在我的代码后面更改字段“状态”时都会更改其文本,以用于调试。
这是我到目前为止所拥有的:
hello\(["|']test["|'"]\)
这是我的看法:
public partial class ReviewsControl : UserControl
{
private Status status = MainControl.AppStatus;
public string StatusDisplay
{
get
{
return status.ToString();
}
}
}
上面的代码甚至什么也没有显示,更不用说动态地执行了。如果我希望XAML在C#代码中检测到更改并相应地更改文本框,该怎么办?
答案 0 :(得分:2)
我也很早就遇到了问题。您的视图(显示给最终用户)并不关心事物的来源或来源,只需知道将在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集,因为整个视图已设置好,只需要绑定到单独的公共属性即可。
答案 1 :(得分:1)
假设TextBlock是UserControl的子元素,即
<TextBlock x:Name="StatusBlock" Text="{Binding StatusDisplay}" ... />
在UserControl的XAML中声明,绑定的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); }
}
}