UWP XAML数据绑定在一个文本框上工作,但不在另一个文本框上工作

时间:2017-08-03 23:32:32

标签: c# xaml data-binding uwp

我遇到了一个特殊的问题,即将两个文本框绑定到同一个对象的数据工作正常,但是在我通过XML反序列化将数据加载回我的程序后,其中一个文本框的绑定失败了。

我使用splitview构建一个小汉堡导航菜单并将我的页面加载到一个框架

以下是我的MainPage.xaml中的相关XAML

<TextBlock Name="PlayerGoldTextBlock" 
                       RelativePanel.RightOf="PlayerNameTextBlock" 
                       RelativePanel.AlignVerticalCenterWithPanel="True" 
                       Foreground="Gold" 
                       FontSize="28" 
                       Text="{x:Bind myGame.Game.Player.Gold, Mode=OneWay}" />    
<TextBlock Name="RemainingTurnsTextBlock" 
                       RelativePanel.RightOf="PlayerGoldTextBlock" 
                       RelativePanel.AlignVerticalCenterWithPanel="True" 
                       Foreground="Red"  
                       Text="{x:Bind myGame.Game.RemainingTurns, Mode=OneWay}" />
<SplitView.Content>
       <Frame Name="MyFrame"></Frame>
</SplitView.Content>

在我加载到框架中的页面中:

<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
    <TextBlock Text="Gold:" HorizontalAlignment="Left" FontSize="16" Margin="0,0,10,0"/>
    <TextBlock Text="{x:Bind myGame.Game.Player.Gold, Mode=OneWay}" HorizontalAlignment="Left" FontSize="16" Margin="0,0,10,0"/>
</StackPanel>
MainPage中的

:加载后PlayerGoldTextBlock无法正确绑定,但RemainingTurnsTextBlock工作正常

在我的框架中:x:绑定myGame.Game.Player.Gold似乎在我加载后重新绑定。

另一件可能相关的事情是,在加载时我会立即看到RemainingTurnsTextBlock更新,但框架中的(工作)玩家黄金直到我导航到另一个框架然后再返回

这是我的反序列化代码,如果重要的话:

async public void LoadGame()
{
    var filename = "testsave.xml";
    var serializer = new XmlSerializer(typeof(GameModel));
    StorageFolder folder = ApplicationData.Current.LocalFolder;
    StorageFile file = await folder.GetFileAsync(filename).AsTask().ConfigureAwait(false);
    Stream stream = await file.OpenStreamForReadAsync().ConfigureAwait(false);

    GameModel myGame;
    using (stream)
    {
        myGame = (GameModel)serializer.Deserialize(stream);
        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 
        {
            this.Player = myGame.Player;
            this.Locations = myGame.Locations;
            this.RemainingTurns = myGame.RemainingTurns;
        });
    }
}

这是我的GameModel的一些属性

public Player Player { get; set; }
public int MaxTurns { get; set; }
private int remainingTurns;
public int RemainingTurns
{
    get { return remainingTurns; }
    set { SetProperty(remainingTurns, value, () => remainingTurns = value);}
}

这是播放器中的黄金属性

private int gold;
public int Gold
{
    get { return gold; }
    set {SetProperty(gold, value, () => gold = value);}
}

这里是setproperty

protected bool SetProperty<T>(T currentValue, T newValue, Action DoSet,
    [CallerMemberName] String property = null)
{
    if (EqualityComparer<T>.Default.Equals(currentValue, newValue)) return false;
    DoSet?.Invoke();
    RaisePropertyChanged(property);
    return true;
}

编辑以根据XY问题评论澄清问题陈述:

  • 我有事情绑定到Game.Player.Gold
  • 在发布时,它们可以正常工作
  • 在进行XML反序列化并加载已保存的状态后,当我离开并返回时,一些绑定工作正常,但有些完全死亡
  • 当我更改播放器实例或其他内容时,绑定似乎不喜欢,因为它无法深入到黄金属性所在的位置。我很奇怪,我导航后框架中的一个文本框可以重新绑定,但主窗口中的一个文本框不能
  • 除了Game.Player.Gold之外,我在Game.Player上直接使用了setter找到了解决方法,但我发现其他属性也出现了类似的问题。
  • 我是否对这些事情彼此看到有什么误解?

2 个答案:

答案 0 :(得分:1)

您没有更新myGame.Game.Player.Gold实时,因此当页面重新加载帧时,它将从Player类中获取详细信息,但是在RemainingTurns发生更改时,它会丢失详细信息以立即更新。框架和主窗口之间可能存在访问器问题。

await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 
{
    this.Player = myGame.Player;
    this.Locations = myGame.Locations;
    this.RemainingTurns = myGame.RemainingTurns;
    // You need to get the value for Player.Gold
});

答案 1 :(得分:0)

我通过在游戏

中添加一个Setter到Player属性来解决这个问题
public Player Player
{
    get { return player; }
    set { SetProperty(player, value, () => player = value); }
}

这似乎触发了任何订阅播放器属性的任何内容的事件。

然而,它并没有修复我看到的不同播放器属性的后载时的所有数据绑定问题。例如,在我导航帧之前,ObservableCollection属性似乎仍然没有绑定。

当我开始游戏时它工作正常,但是在我从XML加载数据之后,即使添加了此修补程序,它仍然需要导航才能正确填充。

我不确定这是否是正确的解决方案,我还有第二个问题,或者这个问题只是针对部分问题的一个奇怪的乐队。这可能是对数据绑定方面或我无法获得的反序列化方面的误解。