我有两个 WPF 控件,但当我刷新其数据绑定时,只有一个控件会刷新



我有一个在 WPF 中创建的BindableGrid控件,并在我的页面上实例化了其中两个:

<Viewbox Name="galaxyViewbox" Width="400" Height="400" DataContext="{x:Static models:Galaxy.Current}">
<local:BindableGrid x:Name="galaxyMap" ArraySource="{Binding StarSystemArray}" CellSize="16" BackgroundImage="/Images/Starfield.png">
<local:BindableGrid.ItemTemplate>
<DataTemplate>
<local:TileView ImagePaths="{Binding ImagePaths}"/>
</DataTemplate>
</local:BindableGrid.ItemTemplate>
</local:BindableGrid>
</Viewbox>
<Viewbox Name="starSystemViewbox" Stretch="Uniform" Grid.RowSpan="2" Grid.Column="1" DataContext="{x:Static models:StarSystem.Current}">
<Grid>
<local:BindableGrid x:Name="starSystemMap" ArraySource="{Binding SpaceObjectArray}" CellSize="64" BackgroundImage="/Images/Starfield.png">
<local:BindableGrid.ItemTemplate>
<DataTemplate>
<local:TileView ImagePaths="{Binding ImagePaths}"/>
</DataTemplate>
</local:BindableGrid.ItemTemplate>
</local:BindableGrid>
...
</Grid>
</Viewbox>

它们都显示适当的图像;但是,当玩家在游戏中占用的当前恒星系统发生变化时,只有starSystemMap控件更新;galaxyMap控件也不会更新(它应该在当前占用的系统上显示飞船图标(。我看不出这些控件的绑定方式有什么不同;每次玩家飞船移动时,我都会调用此代码以强制他们刷新:

galaxyMap.GetBindingExpression(BindableGrid.ArraySourceProperty).UpdateTarget();
starSystemMap.GetBindingExpression(BindableGrid.ArraySourceProperty).UpdateTarget();

我知道还有其他代码与此交互;让我知道您是否还需要查看其他内容才能解决此问题!谢谢!

编辑:分享更多详细信息,首先 BindableGrid.ArraySource:

/// <summary>
/// The array to bind to. Should be a 1D or 2D array.
/// </summary>
public Array ArraySource
{
get { return (Array)GetValue(ArraySourceProperty); }
set { SetValue(ArraySourceProperty, value); }
}
// Using a DependencyProperty as the backing store for ArraySource.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ArraySourceProperty =
DependencyProperty.Register(nameof(ArraySource), typeof(Array), typeof(BindableGrid), new PropertyMetadata(null));

和 BindableGrid.OnPropertyChanged:

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == ArraySourceProperty || e.Property == ItemTemplateProperty || e.Property == CellSizeProperty || e.Property == BackgroundImageProperty)
{
if (ArraySource != null)
{
ColumnDefinitions.Clear();
RowDefinitions.Clear();
int width = ArraySource.GetLength(0);
int height = ArraySource.Rank == 1 ? 1 : ArraySource.GetLength(1);
for (var x = 0; x < width; x++)
ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(CellSize) });
for (var y = 0; y < height; y++)
RowDefinitions.Add(new RowDefinition { Height = new GridLength(CellSize) });
if (ItemTemplate != null)
{
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
var item = ArraySource.Rank == 1 ? ArraySource.GetValue(x) : ArraySource.GetValue(x, y);
var box = Children.Cast<UIElement>().Where(b => (int)b.GetValue(RowProperty) == y && (int)b.GetValue(ColumnProperty) == x && (int)b.GetValue(RowSpanProperty) == 1 && (int)b.GetValue(ColumnSpanProperty) == 1).SingleOrDefault();
if (box == null)
{
box = (UIElement)ItemTemplate.LoadContent();
box.SetValue(ColumnProperty, x);
box.SetValue(RowProperty, y);
Children.Add(box);
}
if (item == Wormholes.Models.StarSystem.Current)
{
}
box.SetValue(DataContextProperty, item);
}
}
}
}
if (bg != null)
bg.Source = BackgroundImage;
else
bg = new Image { Source = BackgroundImage };
if (ColumnDefinitions.Count > 0 && RowDefinitions.Count > 0)
{
bg.SetValue(ColumnSpanProperty, ColumnDefinitions.Count);
bg.SetValue(RowSpanProperty, RowDefinitions.Count);
if (!Children.Contains(bg))
Children.Add(bg);
}
}
}
}

编辑:这是我的 ImagePath 属性,它不会被重新绑定以显示每个恒星系统的最新图像:

public ObservableCollection<string> ImagePaths { get; set; } = new ObservableCollection<string>();
public void RefreshImagePaths()
{
ImagePaths.Clear();
ImagePaths.Add("Star");
if (Current == this)
{
foreach (var ip in PlayerShip.Instance.ImagePaths)
ImagePaths.Add(ip);
}
}

RefreshImagePaths在你移出的星系统上调用,当你改变星星系统时,你进入的星系统。

编辑:真正有趣的是,我在绑定 BindableGrid 时调用box.SetValue(DataContextProperty, item);,但 UI 没有针对星系图更新......

编辑:这是我的TileView.xaml.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Wormholes.Views
{
/// <summary>
/// Interaction logic for TileView.xaml
/// </summary>
public partial class TileView : UserControl
{
public TileView()
{
InitializeComponent();
}
/// <summary>
/// Paths to images to display, from back to front Z-index.
/// </summary>
public ObservableCollection<string> ImagePaths
{
get { return (ObservableCollection<string>)GetValue(ImagePathsProperty); }
set { SetValue(ImagePathsProperty, value); }
}
// Using a DependencyProperty as the backing store for ImagePaths.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ImagePathsProperty =
DependencyProperty.Register(nameof(ImagePaths), typeof(ObservableCollection<string>), typeof(TileView), new PropertyMetadata(null));
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == ImagePathsProperty)
{
grid.Children.Clear();
if (ImagePaths != null)
{
foreach (var ip in ImagePaths)
{
try
{
var img = new Image { Source = new BitmapImage(new Uri(System.IO.Path.GetFullPath(System.IO.Path.Combine("Images", ip + ".png")), UriKind.RelativeOrAbsolute)), Width = Width, Height = Height };
grid.Children.Add(img);
}
catch (FileNotFoundException ex)
{
Console.Error.WriteLine($"Could not find image: {ip}");
}
catch (DirectoryNotFoundException ex)
{
Console.Error.WriteLine($"Could not find image: {ip}");
}
}
}
}
}
}
}

TileViewOnPropertyChanged方法从未被调用过,因为TileView的DataContext和ImagePaths从未真正改变过;只有里面的项ImagePaths改变。因此,我不得不强制刷新BindableGrid.OnPropertyChanged

box.DataContext = null;
box.DataContext = item;

我相信有更好的方法可以做到这一点,但现在,它有效!

最新更新