UWP XAML: Bindings.Update() 不会触发内部项目
UWP XAML: Bindings.Update() doesn't trigger inner items
如果我有带有 x:Bind
绑定的 GridView 项,调用 Bindings.Update()
无效。 None 的 Items 绑定属性被再次读取。它停留在第一次初始化的值上。
但是 Bindings.Update() 可以完美地触发绑定属性的顶级重新读取(如 Width="{x:Bind GridWidth}"
)。我在页面调整大小事件中调用 Bindings.Update()。
如何强制 Xaml 重新读取项目属性?项目列表本身没有改变(列表 count/content),只有 一些 的项目属性(如 Width="{x:Bind ItemWidth}"
)。
示例:
<!-- Working, re-read -->
<Grid Width="{x:Bind GridWidth}">
<GridView x:Name="barGrid" ItemsSource="{x:Bind projects}" Background="Aqua" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:Name="DoubleBars" x:DataType="local:Project">
<!-- This isn't re-read !!! !!! !!! -->
<StackPanel x:Name="projectItemStack" Width="{x:Bind ItemWidth}" Background="Orange">
<Grid>
<Rectangle x:Name="RedBar" Fill="Red"/>
<TextBlock Text="Test0"/>
</Grid>
<Grid Margin="0, 3, 0, 5">
<Rectangle x:Name="GreenBar" Fill="Lime"/>
<TextBlock Text="Test1"/>
</Grid>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate/>
</GridView.ItemsPanel>
</GridView>
</Grid>
如果你想实现 属性 从绑定对象(项目 class)更改更新,你必须使对象(项目 class)实现 INotifyPropertyChanged Interface and make the Property subscribe the PropertyChanged event, meanwhile, you should also specific that the x:Bind mode to be OneWay or a TwoWay. More details about binding in UWP app, you can learn from Data binding主题。
为了澄清这一点,我根据您的 xaml 代码创建了一个示例。
这里是 Project
class 实现了 INotifyPropertyChanged Interface.
public class Project:INotifyPropertyChanged
{
private double itemWidth;
public double ItemWidth
{
get
{
return itemWidth;
}
set
{
itemWidth = value;
OnPropertyChanged("ItemWidth");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在 xaml 中,我更改了您的代码以添加一个按钮来更改项目的 属性 并将 x:Bind 模式设置为 OneWay,更多区别请看BindingMode Enum.
<Grid Width="{x:Bind GridWidth}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GridView x:Name="barGrid" ItemsSource="{x:Bind projects,Mode=OneWay}" Background="Aqua" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:Name="DoubleBars" x:DataType="local:Project">
<!-- This isn't re-read !!! !!! !!! -->
<StackPanel x:Name="projectItemStack" Width="{x:Bind ItemWidth,Mode=OneWay}" Background="Orange">
<Grid>
<Rectangle x:Name="RedBar" Fill="Red"/>
<TextBlock Text="Test0"/>
</Grid>
<Grid Margin="0, 3, 0, 5">
<Rectangle x:Name="GreenBar" Fill="Lime"/>
<TextBlock Text="Test1"/>
</Grid>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate/>
</GridView.ItemsPanel>
</GridView>
<Button Click="Button_Click" Content="Click me to change the Items width"/>
</Grid>
这是后面的page.xaml.cs代码,
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
projects = new ObservableCollection<Project>();
projects.Add(new Project { ItemWidth = 300 });
projects.Add(new Project { ItemWidth = 400 });
projects.Add(new Project { ItemWidth = 500 });
projects.Add(new Project { ItemWidth = 600 });
projects.Add(new Project { ItemWidth = 700 });
}
ObservableCollection<Project> projects;
public double GridWidth { get; set; } = 1000;
private void Button_Click(object sender, RoutedEventArgs e)
{
foreach(var item in projects)
{
item.ItemWidth += 100;
}
}
}
然后当你点击Button并改变ItemWidth
属性时你可以看到变化。
如果我有带有 x:Bind
绑定的 GridView 项,调用 Bindings.Update()
无效。 None 的 Items 绑定属性被再次读取。它停留在第一次初始化的值上。
但是 Bindings.Update() 可以完美地触发绑定属性的顶级重新读取(如 Width="{x:Bind GridWidth}"
)。我在页面调整大小事件中调用 Bindings.Update()。
如何强制 Xaml 重新读取项目属性?项目列表本身没有改变(列表 count/content),只有 一些 的项目属性(如 Width="{x:Bind ItemWidth}"
)。
示例:
<!-- Working, re-read -->
<Grid Width="{x:Bind GridWidth}">
<GridView x:Name="barGrid" ItemsSource="{x:Bind projects}" Background="Aqua" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:Name="DoubleBars" x:DataType="local:Project">
<!-- This isn't re-read !!! !!! !!! -->
<StackPanel x:Name="projectItemStack" Width="{x:Bind ItemWidth}" Background="Orange">
<Grid>
<Rectangle x:Name="RedBar" Fill="Red"/>
<TextBlock Text="Test0"/>
</Grid>
<Grid Margin="0, 3, 0, 5">
<Rectangle x:Name="GreenBar" Fill="Lime"/>
<TextBlock Text="Test1"/>
</Grid>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate/>
</GridView.ItemsPanel>
</GridView>
</Grid>
如果你想实现 属性 从绑定对象(项目 class)更改更新,你必须使对象(项目 class)实现 INotifyPropertyChanged Interface and make the Property subscribe the PropertyChanged event, meanwhile, you should also specific that the x:Bind mode to be OneWay or a TwoWay. More details about binding in UWP app, you can learn from Data binding主题。
为了澄清这一点,我根据您的 xaml 代码创建了一个示例。
这里是 Project
class 实现了 INotifyPropertyChanged Interface.
public class Project:INotifyPropertyChanged
{
private double itemWidth;
public double ItemWidth
{
get
{
return itemWidth;
}
set
{
itemWidth = value;
OnPropertyChanged("ItemWidth");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在 xaml 中,我更改了您的代码以添加一个按钮来更改项目的 属性 并将 x:Bind 模式设置为 OneWay,更多区别请看BindingMode Enum.
<Grid Width="{x:Bind GridWidth}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GridView x:Name="barGrid" ItemsSource="{x:Bind projects,Mode=OneWay}" Background="Aqua" Grid.Row="0">
<GridView.ItemTemplate>
<DataTemplate x:Name="DoubleBars" x:DataType="local:Project">
<!-- This isn't re-read !!! !!! !!! -->
<StackPanel x:Name="projectItemStack" Width="{x:Bind ItemWidth,Mode=OneWay}" Background="Orange">
<Grid>
<Rectangle x:Name="RedBar" Fill="Red"/>
<TextBlock Text="Test0"/>
</Grid>
<Grid Margin="0, 3, 0, 5">
<Rectangle x:Name="GreenBar" Fill="Lime"/>
<TextBlock Text="Test1"/>
</Grid>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate/>
</GridView.ItemsPanel>
</GridView>
<Button Click="Button_Click" Content="Click me to change the Items width"/>
</Grid>
这是后面的page.xaml.cs代码,
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
projects = new ObservableCollection<Project>();
projects.Add(new Project { ItemWidth = 300 });
projects.Add(new Project { ItemWidth = 400 });
projects.Add(new Project { ItemWidth = 500 });
projects.Add(new Project { ItemWidth = 600 });
projects.Add(new Project { ItemWidth = 700 });
}
ObservableCollection<Project> projects;
public double GridWidth { get; set; } = 1000;
private void Button_Click(object sender, RoutedEventArgs e)
{
foreach(var item in projects)
{
item.ItemWidth += 100;
}
}
}
然后当你点击Button并改变ItemWidth
属性时你可以看到变化。