我在設定自動系結時遇到問題。
我有一個簡單的 WPF 應用程式,它有兩個類 - MovieInfo(包含有關我的檔案系統上的電影檔案的資訊)和一個MediaScanner只回傳List<MovieInfo>. 在我的 MainWindow.xaml 中,我有一個ListBox:
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="242" Margin="10,35,0,0" VerticalAlignment="Top" Width="237" d:ItemsSource="{Binding MovieList}"/>
同樣在 XAML 中添加了<Window ...>is
Name="MainWindow1"
DataContext="{Binding ElementName=MainWindow1}"
在后面的代碼中,我創建了一個公共屬性MainWindow : Window:
public ObservableCollection<MovieInfo> MovieList { get; set; }
在建構式中:
public MainWindow()
{
DataContext = this;
MovieList = new ObservableCollection<MovieInfo>();
InitializeComponent();
//this doesn't do anything for me
//listBox.ItemsSource = MovieList;
}
我有一個按鈕呼叫:
private void button_Click(object sender, RoutedEventArgs e)
{
var scanner = new MediaScanner();
MovieList = new ObservableCollection<MovieInfo>(scanner.ScanAll().OrderBy(x => x.Title));
//listBox.ItemsSource = MovieList;
}
我的理解是這應該處理所有事情,但除非我取消注釋它在 button_Click 中ListBox的位置,否則它不會填充。listBox.ItemsSource = MovieList;
我錯過了什么?
uj5u.com熱心網友回復:
ListBox不會MovieList在運行時系結,因為您以.為前綴ItemsSourced。
添加命名空間后,您可以將
d:任何屬性或控制元件放在前面,使其僅在 XAML 設計器中顯示,而不在運行時顯示。[...]您可以使用
d:任何 UWP 或 WPF .NET Core 控制元件的屬性,例如顏色、字體大小和間距。您甚至可以將其添加到控制元件本身。
這些命名空間是在 XAML 根元素上定義的。
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
為了使系結在運行時作業,洗掉d:或添加另一個ItemsSource不帶d:前綴的系結,以便您有不同的設計和運行時源。
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="242" Margin="10,35,0,0" VerticalAlignment="Top" Width="237" ItemsSource="{Binding MovieList}"/>
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="242" Margin="10,35,0,0" VerticalAlignment="Top" Width="237" d:ItemsSource="{Binding DesignTimeMovieList}" ItemsSource="{Binding MovieList}"/>
另一個問題是您既沒有為電影串列集合實作依賴屬性INotifyPropertyChanged,也沒有為. 實際上,這意味著盡管您MovieList在按鈕單擊事件處理程式中為屬性分配了一個新集合,但系結不會收到更改通知,并且仍將使用舊集合實體。當然listBox.ItemsSource = MovieList;可以在這里作業,但它直接分配集合并覆寫系結,所以這是一個不同的解決方案。
從長遠來看,您可能應該應用 MVVM 模式并將要系結的資料分離到實作的視圖模型中INotifyPropertyChanged,這可以解決您的問題,同時將您的視圖與邏輯和資料分開,然后通過系結連接。
視窗的依賴屬性示例。
public partial class MainWindow : Window
{
public ObservableCollection<MovieInfo> MovieList
{
get => (ObservableCollection<MovieInfo>)GetValue(MovieListProperty);
set => SetValue(MovieListProperty, value);
}
public static readonly DependencyProperty MovieListProperty = DependencyProperty.Register(
nameof(MovieList), typeof(ObservableCollection<MovieInfo>), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
DataContext = this;
MovieList = new ObservableCollection<MovieInfo>();
InitializeComponent();
// ...other code.
}
private void button_Click(object sender, RoutedEventArgs e)
{
var scanner = new MediaScanner();
MovieList = new ObservableCollection<MovieInfo>(scanner.ScanAll().OrderBy(x => x.Title));
}
// ...other code.
}
Example for a view model in case you want to move to MVVM.
public class MyViewModel : INotifyPropertyChanged
{
private ObservableCollection<MovieInfo> _movieList;
public ObservableCollection<MovieInfo> MovieList
{
get => _movieList;
set
{
if (_movieList == value)
return;
_movieList = value;
OnPropertyChanged();
}
}
// ...other code.
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
As a final remark, you should consider reusing the ObservableCollection<MovieInfo> MovieList instead of creating and assigning a new one each time. This type of collection provides change notifications for adding, removing and replacing items, which will automatically be reflected in the user interface. Exposing an observable collection, but instead of modifying, replacing it, is pointless. If a collection is always replaced, a simple List<T> will do the same.
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/435602.html
上一篇:資源字典作為NuGet包
