我有以下的類層次結構:爲什麼ListView中的DataTemplate不會自動更新其綁定?
namespace WpfBindingProblem
{
public class Top
{
public IList<Mid> MidList { get; } = new ObservableCollection<Mid>();
}
public class Mid
{
public IList<Bot> BotList { get; } = new ObservableCollection<Bot>();
}
public class Bot
{
}
}
而且我有這樣的XAML窗口:
<Window x:Class="WpfBindingProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfBindingProblem"
mc:Ignorable="d"
Title="MainWindow" Height="217.267" Width="333.686">
<Window.DataContext>
<local:Top/>
</Window.DataContext>
<Window.Resources>
<local:TriggersToString x:Key="TriggersToString"/>
</Window.Resources>
<Grid>
<ListView Margin="10" ItemsSource="{Binding MidList}" x:Name="ThatList">
<ListView.Resources>
<DataTemplate DataType="{x:Type local:Mid}">
<TextBlock Text="{Binding BotList, Converter={StaticResource TriggersToString}}" />
</DataTemplate>
</ListView.Resources>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Add mid" Click="AddMid"/>
<MenuItem Header="Add bot to selected mid" Click="AddBot" />
</ContextMenu>
</ListView.ContextMenu>
<ListView.View>
<GridView>
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
有了這些處理程序:
namespace WpfBindingProblem
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void AddMid(object sender, RoutedEventArgs e)
{
if(DataContext is Top p)
{
p.MidList.Add(new Mid());
}
}
private void AddBot(object sender, RoutedEventArgs e)
{
if(ThatList.SelectedItem is Mid c)
{
c.BotList.Add(new Bot());
}
}
}
}
而這種轉換器(作爲一個替身適用於任意轉換器):
namespace WpfBindingProblem
{
[ValueConversion(typeof(IList<Bot>), typeof(string))]
public class TriggersToString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is IList<Bot> list)
{
return list.Count.ToString();
}
throw new InvalidOperationException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException();
}
}
}
在出現,當我們運行這個例子,我可以右擊並選擇「添加中旬」這樣的Mid
一個實例添加到Top
數據上下文和列表視圖相應更新,顯示窗口號碼0(如變換邏輯)
然而,當我點擊「添加漫遊器來選擇中間」,的Bot
一個實例被添加到所選擇的Mid
(I可以驗證這一點使用斷點),但是列表視圖是沒有相應的更新(我預計0改爲1,但轉換器不爲Mid
特定情況下再次調用)。
爲什麼會發生這種變化不會觸發GUI的更新?
我知道我可以通過一些竅門解決這個問題(比如將數據上下文設置爲null
並返回,或者可能通過使用依賴屬性調用顯式更新),但有兩個原因可以避免這種情況:
- 我的實際代碼比這個MCVE更復雜,它看起來非常難看。
- 我已經爲所有需要的
ObservableCollection
s和INotifyPropertyChanged
接口灑滿了所有我的(實際)類,這樣我就不需要執行手動更新了 - 所以我覺得在這種情況下應該會發生自動更新,除非我錯過了一些東西。
' '應該更新UI。這是因爲當你添加一個元素時,BotList屬性本身不會改變。但是,它的計數屬性呢。 –
Clemens
@Clemens我明白了。但是,這是特定於此特定的轉換器,其邏輯可以在XAML中複製。有沒有更通用的方法,以便我可以使用任意的轉換器? –
我不知道任何。通過在BotList中添加或刪除元素,{Binding BotList}不會被觸發。 – Clemens