我目前正在做一个项目,我主要关注后端,我知道这个 XAML 代码不是好的做法。我不太习惯 INotifyPropertyChanged 接口,而且我真的很难看到错误。当我调试程序时,TourName 不为空,它从 liveTourAppointment.tour.name 获取值;但是当我运行它时窗口中的标签保持为空
这是我尝试过的:
XAML代码:
<Grid>
<Label x:Name ="Label" Content="{Binding Path=TourName}" Margin="82,44,579,354"/>
</Grid>
</Window>
后面的代码在这里:
public partial class LiveTourWin : Window, INotifyPropertyChanged
{
public TourAppointment liveTourAppointment { get; set; }
private string _tourName =".";
public string TourName
{
get { return _tourName; }
set
{
{
if (value != _tourName)
{
_tourName = value;
OnPropertyChanged(nameof(TourName));
}
}
}
}
private readonly TourAppointmentController _tourAppointmentController;
public LiveTourWin(int guideId)
{
InitializeComponent();
this.DataContext = this;
_tourAppointmentController = new TourAppointmentController();
liveTourAppointment = _tourAppointmentController.GetLiveTour(guideId);
this.TourName = liveTourAppointment.tour.name;
}
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler? PropertyChanged;
}
}
嘿,GPT-4 完全做到了,所以不要指望它会起作用:
看起来您正在 LiveTourWin 类的构造函数中设置 TourName 的值,但您没有引发 PropertyChanged 事件来通知 UI 该值已更改。
要解决此问题,您可以在 TourName 属性的 set 方法中引发 PropertyChanged 事件,如下所示:
private string _tourName = ".";
public string TourName
{
get { return _tourName; }
set
{
if (value != _tourName)
{
_tourName = value;
OnPropertyChanged(nameof(TourName));
}
}
}
然后在 LiveTourWin 类的构造函数中,您可以像这样设置 TourName 属性:
liveTourAppointment = _tourAppointmentController.GetLiveTour(guideId);
TourName = liveTourAppointment.tour.name;
这样,当 TourName 属性被设置时,将引发 PropertyChanged 事件,并通知 UI 更新标签的内容。
此外,值得注意的是,在您的 XAML 代码中,您绑定到 TourName 属性,但没有为标签指定 DataContext。在您的构造函数中,您将窗口的 DataContext 设置为此,这意味着标签将从窗口继承 DataContext,因此将找到 TourName 属性。因此,对于这种特殊情况,您无需在 XAML 代码中执行任何其他操作。
您的绑定已找到。你的问题是边距。您正在做一些绝对设置。尽量不要那样做。 “窗口”中的每个对象(例如您的网格对象)都会占用整个可用空间。很像浏览器。您调整窗口大小,通常会自动调整列等。
为此,请在窗口中分配空间并自动调整以允许收缩/扩展。现在,怎么做。
<Grid>
<!-- Example of 3 equally sized columns -->
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- multiple rows with different fixed heights.
The last row with "*" means take up all unused space for the rest -->
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Place whatever controls at specific row/column locations -->
<Label Grid.Row="3" Grid.Column="2" (rest of label content />
</Grid>
此外,您可以分配最小尺寸加上“”以允许基于可用的拉伸,如下所示。这有 3 列。第一列固定为 120 像素,但其余两列具有预定义的最小值,但由于“”在两列上,因此它们可以根据可用情况拉伸或收缩。所以,假设窗口是 800 宽。第一个仍然是 120,第二个和第三个分别得到 200 和 350,总共 670,还剩下 130。由于两列有“*”,每列的宽度将增加 65。这同样适用于行定义。
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="200*" />
<ColumnDefinition Width="350*" />
</Grid.ColumnDefinitions>
还有其他类型的控件、StackPanel、DockPanel 等允许其他格式和对齐选项。
所以,您的绑定有效,但是如果您给它一个预先分配空间的指定位置,因为您最终将准备您的用户界面,制作适合您的东西,而不用担心“固定”边距等。
附加说明,对于标签,因为它们通常预先生成一次,您可能需要添加到绑定子句中,例如
<Label x:Name ="Label" Content="{Binding Path=TourName, NotifyOnSourceUpdated=True}" />