none
关于数据动态绑定细节的问题。 RRS feed

  • 问题

  • 开发中碰到一个问题,描述如下:

    1、Page1有个ListView控件,对其进行数据绑定到类classA,假设classA的属性name在ListView上显示为“Lemon”。

    2、由于数据更新,classA的属性name更改为了“Mike”,并调用了PropertyChanged(),同时切换到Page2。

    3、从Page2返回到Page1,发现ListView控件先显示“Lemon”然后显示成"Mike"。

    请问如何避免上述现象?期望返回Page1时能够直接显示为“Mike”

    2012年8月15日 6:35

答案

  • Hi,

    其实是一样的,绑定一个BitmapImage类到Image的Source属性上,其实你绑定字符串上去,Win8Style内部也是会自动生成BitmapImage之后放上去的,我们现在做的只是把这个自动生成的步骤手动的做到。因为自动生成的话会有时间的差距。你可以试一下我的方法我在RTM上面感觉时间差距比较小。

    我写的例子:

    XAML:

    <StackPanel Name="stack" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Image  Name="image" Source="{Binding Image}"  />
            <Button Content="button" Click="Button_Click_1" />
        </StackPanel>

    C#:

    public sealed partial class MainPage : Page
        {
    
            MyClass myClass=new MyClass();
            BitmapImage bitmapImage;
    
            public MainPage()
            {
                this.InitializeComponent();
    
                
    
                bitmapImage = new BitmapImage(new Uri("ms-appx:///image/test1.jpg"));
                myClass.Image = bitmapImage;
                this.stack.DataContext = myClass;
    
                
            }
    
            public class MyClass:BindableBase
            {
                private BitmapImage image;
                public BitmapImage Image
                {
                    get { return this.image; }
                    set { SetProperty(ref this.image, value); }
                }
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                bitmapImage = new BitmapImage(new Uri("ms-appx:///image/test2.jpg"));
                myClass.Image = bitmapImage;
            }

    我在自己定义的类当中继承了BindableBase这个VS提供的模板,实际上它的作用就是实现INotifyPropertyChanged接口,我对c++不熟悉不知道那里面有没有这个模板,如果没有你可以自己来实现,不过这个如果是你自己定义的类进行绑定的话必须要实现的借口,通知绑定引擎数据发生改变就是通过这个借口的。


    Aaron Xue [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年8月23日 5:50
    版主

全部回复

  • Hi,

    能把重现这个问题的代码贴一下吗?


    Aaron Xue [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年8月16日 8:16
    版主
  • ListView绑定的数据源类

     [Windows::UI::Xaml::Data::Bindable]
     public ref class TourneyInfoDisplayTemplate sealed: public Platform::Object ,public INotifyPropertyChanged
     {
     public:
      TourneyInfoDisplayTemplate()
      {
       
      }
      ~TourneyInfoDisplayTemplate()
      {

      }
      property String^ TourneyName;
      property String^ SignupAmount;
      property String^ Type;
      property String^ IsSignup;
      property Object^ Tag;
      virtual event PropertyChangedEventHandler^ PropertyChanged;
      void setIsSignup(bool flag);
      void setSignupAmount(int amount);
      void setType(int type, __time64_t time);
      void setTourneyName(String^ name);
     protected:
      void RaisePropertyChanged(String^ name);
     };

    需要更改的属性,是根据参数设定显示的图片路径:

    void TourneyInfoDisplayTemplate::setIsSignup(bool flag)
     {
      if(flag)
      {
       IsSignup = "Assets/is_signup.png";
      }
      else
      {
       IsSignup = "";
      }
      TourneyInfoDisplayTemplate::RaisePropertyChanged("IsSignup");
     }

    双击列表的某一行,会调用上面的函数置true,同时从Page1切换到Page2;

    从Page2点返回,会调用这个函数置false,同时从Page2切换到Page1;

    从逻辑上看,返回Page1后不应该看到图片了,但实际情况是图片仍然存在,过会自动消失。

    2012年8月21日 1:37
  • 给那个Image绑定一个Visibility属性试试?动态设置可见性

    2012年8月22日 7:53
  • Hi,

    我写了一个程序证实了这个问题。虽然不是通过页面导航的方式,但也可以说明问题。

    我发现,新建一个类之后添加字符串,并将Image的Source属性绑定到字符串上,之后对字符串进行更改在vs2012RC版有明显的卡顿,但RTM好很多基本上感觉不出。我用了另外一种方式就是手动的新建一个BitmapImage类,之后重新设置Uri感觉这样的速度也会快很多。

    所以我的建议是或者你可以手动的去写BitmapImage类添加Uri并且在代码中更改Uri,或者是PnFWorkshop给出的方法可以对visibility属性进行绑定。


    Aaron Xue [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    2012年8月22日 9:20
    版主
  • 不好意思,我刚接触metro不久,不太理解新建一个BitmapImage如何绑定到ListView中,麻烦给个代码列子,下面是ListView的代码:

    <ListView x:Name ="TourneyList" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="554" ItemsSource="{Binding}" Foreground="#FF4AF2FC" SelectionChanged="TourneyListBoxSelectChanged" DoubleTapped="TourneyListDoubleTapped" SelectionMode="Single"  IsTabStop="False" ItemContainerStyle="{StaticResource TourneyListItemStyle}" IsSwipeEnabled="False">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <Grid Width="{Binding ElementName=TourneyList, Path=Width, Converter={StaticResource gridConverter}}" HorizontalAlignment="Left" Margin="0">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="15*"/>
                                    <ColumnDefinition Width="3*"/>
                                    <ColumnDefinition Width="3*"/>
                                    <ColumnDefinition Width="2*"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock  Grid.Column="0" Text="{Binding TourneyName}" FontSize="{StaticResource FontSize20}" VerticalAlignment="Center" HorizontalAlignment="Left" TextTrimming="WordEllipsis"/>
                                <TextBlock  Grid.Column="1" Text ="{Binding SignupAmount}" FontSize="{StaticResource FontSize20}" VerticalAlignment="Center" HorizontalAlignment="Right"/>
                                <TextBlock  Grid.Column="2" Text ="{Binding Type}" FontSize="{StaticResource FontSize20}" VerticalAlignment="Center" HorizontalAlignment="Right"/>

                                //问题所在

                                <Image Grid.Column="3" Source="{Binding IsSignup}" VerticalAlignment="Center" HorizontalAlignment="Right" Height="Auto" Width="Auto"/>
                            </Grid>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>    

    2012年8月22日 10:02
  • Hi,

    其实是一样的,绑定一个BitmapImage类到Image的Source属性上,其实你绑定字符串上去,Win8Style内部也是会自动生成BitmapImage之后放上去的,我们现在做的只是把这个自动生成的步骤手动的做到。因为自动生成的话会有时间的差距。你可以试一下我的方法我在RTM上面感觉时间差距比较小。

    我写的例子:

    XAML:

    <StackPanel Name="stack" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Image  Name="image" Source="{Binding Image}"  />
            <Button Content="button" Click="Button_Click_1" />
        </StackPanel>

    C#:

    public sealed partial class MainPage : Page
        {
    
            MyClass myClass=new MyClass();
            BitmapImage bitmapImage;
    
            public MainPage()
            {
                this.InitializeComponent();
    
                
    
                bitmapImage = new BitmapImage(new Uri("ms-appx:///image/test1.jpg"));
                myClass.Image = bitmapImage;
                this.stack.DataContext = myClass;
    
                
            }
    
            public class MyClass:BindableBase
            {
                private BitmapImage image;
                public BitmapImage Image
                {
                    get { return this.image; }
                    set { SetProperty(ref this.image, value); }
                }
            }
    
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                bitmapImage = new BitmapImage(new Uri("ms-appx:///image/test2.jpg"));
                myClass.Image = bitmapImage;
            }

    我在自己定义的类当中继承了BindableBase这个VS提供的模板,实际上它的作用就是实现INotifyPropertyChanged接口,我对c++不熟悉不知道那里面有没有这个模板,如果没有你可以自己来实现,不过这个如果是你自己定义的类进行绑定的话必须要实现的借口,通知绑定引擎数据发生改变就是通过这个借口的。


    Aaron Xue [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年8月23日 5:50
    版主