我試圖直接系結到一個模型(類似于這里的情況),而不是該模型上的屬性,但它不起作用。我之前問過一個關于這個的問題,答案在 UWP 中有效。我現在在 WinUI3(打包的 UWP)中作業,不確定是否適用相同的解決方案。
我有一堂課:
public class Message
{
public string Title { get; set; }
public string Content { get; set; }
}
我有一個顯示該類的 UserControl:
public sealed partial class MessageControl : UserControl
{
/// <summary>
/// The message to display.
/// </summary>
public Message Message { get; set; }
public MessageControl()
{
this.InitializeComponent();
}
}
使用 XAML:
<UserControl
x:Class="MessageClient.Controls.EmailControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MessageClient.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<StackPanel>
<!-- Displays the title of the message. -->
<TextBlock Name="HeaderTextBlock"
Text="{x:Bind Message.Title, Mode=OneWay}"></TextBlock>
<!-- Displays the content of the message. -->
<TextBlock Name="ContentPreviewTextBlock"
Text="{x:Bind Message.Content, Mode=OneWay}"></TextBlock>
</StackPanel>
</Grid>
</UserControl>
現在,我有一個在串列視圖內顯示該控制元件的視窗:
<Window
x:Class="MessageClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:EmailClient"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:MessageClient.Controls" xmlns:models="using:MessageClient.Models"
mc:Ignorable="d">
<Grid>
<!-- The list of messages. -->
<ListView x:Name="MessagesListView"
ItemsSource="{x:Bind Messages}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Message">
<controls:MessageControl Margin="5"
Message="{x:Bind Mode=OneWay}"></controls:MessageControl>
<!-- TEST 1 -->
<!--<TextBlock Text="{x:Bind Title}"></TextBlock>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!-- TEST 2 -->
<!--<controls:MessageControl Message="{x:Bind TestMessage, Mode=OneWay}"></controls:MessageControl>-->
</Grid>
</Window>
Window 背后的代碼是:
public sealed partial class MainWindow : Window
{
public ObservableCollection<Message> Messages;
public Message TestMessage;
public MainWindow()
{
this.InitializeComponent();
// Populate the test message.
this.PopulateTestMessages();
}
private void PopulateTestMessages()
{
// The TestDataGenerator just returns a staticaly defined list of test messages.
this.Messages = new ObservableCollection<Message>(TestDataGenerator.GetTestMessages(10));
this.TestMessage = this.Messages.First();
}
}
When I run this code (which compiles and runs), I get a window with the expected number of items in the ListView (10), but they are all blank. There are also no XAML binding failures being reported (via the new feature in Visual Studio 2022). In an attempt to investigate this, I added in a textblock inside of the listview (denoted as TEST 1 in the comments) bound to the Title property of the Message. This worked as expected, displaying the correct titles for the 10 messages. I then added a single MessageControl to the Window outside of the ListView (denoted as TEST 2 in the comments) bound to a single Message property on the Window. This also worked exactly as expected.
我錯過了什么嗎?為什么直接系結到模型的特定情況(而不是該模型上的屬性 - 即沒有路徑的系結)不起作用,當資料在那里并且與其他系結配置一起使用時?
uj5u.com熱心網友回復:
事實證明,這個特定案例公開了 XAML 中系結如何作業的一些順序。要了解這里發生的事情:
- 所述
Window正在初始化,該初始化它的UI,包括ListView。 - 在
Message隨后的模型被檢索并添加到ObservableCollection。 - 當每個
Message都添加到 時ObservableCollection,ListView使用它ObservableCollection作為它的ItemsSource然后Item使用ItemTemplateXAML 中指定的創建一個新的,然后初始化并將新初始化的系結MessageControl到Message. TEST 1 驗證這是否正在發生。
這里的問題是在第 3 步:MessageControls 被初始化然后系結到。當系結發生時,UI 永遠不會被通知它需要更新系結。這就是為什么添加Mode=OneWay到{x:Bind}不能解決問題的原因。該OneWay模式告訴系結更新每當更新模型......但XAML依然是從來沒有意識到對模型進行了更新。
我不完全確定為什么這與其他兩個系結(TEST 1 和 TEST 2 注釋)不同,但這似乎是用戶定義型別(類)的問題,而不是原始型別或內置型別屬性(例如string和int)。
修復方法是使模型能夠通知(或“通知”)已更新的 UI。這是通過實作INotifyPropertyChanged介面完成的。更新MessageControl為:
public sealed partial class MessageControl : UserControl, INotifyPropertyChanged
{
private Message _message;
/// <summary>
/// The message to display.
/// </summary>
public Message Message
{
get { return this._message; }
set
{
this._message = value;
this.RaisePropertyChanged("Message");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public EmailControl()
{
this.InitializeComponent();
}
}
最后一點:INotifyPropertyChanged必須在 上執行MessageControl此操作才能作業。如果模型的特定屬性更新,則INotifyPropertyChanged在Message模型上實作將允許MessageControl(或任何其他資料系結 UI,例如注釋的 TEST 1)Message更新,但不會在更新時解決Message模型本身的問題MessageControl。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/369834.html
上一篇:WPF應用程式中看不到按鈕的影像
