0

I display a list of fullname of Member and when I select a member, it will go to the detail page. I edit info directly in the textbox and then click Save in application bar but the info is not changed as I edited...it still remains the old value

Plz help me!

I have the List name of member like this

<ListBox x:Name="Listmember" Height="500" SelectionChanged="Listmember_SelectionChanged" ItemsSource="{Binding Data}" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Width="466" Margin="0, 0, 0, 12">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Grid Grid.Column="0"></Grid>
                        <StackPanel Grid.Column="1" >
                            <TextBlock FontSize="40"   Text="{Binding FullName}" Foreground="#FFEA0909" FontWeight="Normal" FontStyle="Normal" Style="{StaticResource PhoneTextTitle3Style}" TextWrapping="Wrap"/>


                        </StackPanel>
                        <Grid Grid.Column="2">
                            <Button x:Name="Deletebutton" Height="60" Width="60" Click="deleteButton_Click" BorderBrush="{StaticResource TransparentBrush}">

                                <Image Source="/Assets/delete.dark.png" Visibility="{StaticResource PhoneDarkThemeVisibility}" Margin="-24"/>
                            </Button>
                        </Grid>
                    </Grid>

                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

and the SelectionChanged is:

private void Listmember_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        // If no customer is selected, just return
        if (Listmember.SelectedItem == null) return;
        // Get the parent application that contains the customer being edited
        App thisApp = Application.Current as App;

        // Set this to the selected customer
        thisApp.SelectedMember = Listmember.SelectedItem as Member;

        // Navigate to the detail page
        NavigationService.Navigate(new Uri("/View/MemberDetail.xaml", UriKind.RelativeOrAbsolute));

    }

In the MemberDetails.xaml which is navigated to:

<Grid Name="ListDetails" Grid.Row="0">
            <TextBlock Grid.Row="0" Name="fn" Text="FullName" FontSize="30" VerticalAlignment="Bottom"/>
            <TextBox Grid.Row="1" Name="fullnameTextBox" Text="{Binding FullName, Mode=TwoWay}" TextWrapping="Wrap"/>
            <TextBlock Grid.Row="2" Name="ad" Text="Address" FontSize="30" VerticalAlignment="Bottom"/>
            <TextBox Grid.Row="3" Name="addressTextBox" Text="{Binding Address, Mode=TwoWay}" TextWrapping="Wrap" />
 </Grid>
 <phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton 
            IconUri="/Images/save.png" 
            Text="Save" 
            x:Name="SaveButton" 
            Click="Save_Click"/>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

and the code behind

 public MemberDetail()
    {
        InitializeComponent();
        this.DataContext = App.MainViewModel;
    }
    ViewDetails view = new ViewDetails();



    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        // Get the parent application that contains the active custom
        App thisApp = Application.Current as App;

        // Load the active customer into the viewmodel
        view.LoadDetails(thisApp.SelectedMember);

        // Set the data context to the viewmodel
        ListDetails.DataContext = view;

    }




 private void Save_Click(object sender, EventArgs e)
        {
            App thisApp = Application.Current as App;

           view.UpdateDetails(thisApp.SelectedMember);

            // Go back to the previous page
            NavigationService.GoBack();
        }

and class ViewDetails in ViewModel:

public class ViewDetails : INotifyPropertyChanged
{

    private string _fullname;

    public string FullName
    {
        get
        {
            return _fullname;
        }
        set
        {
            _fullname = value;

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Fullname"));
            }
        }
    }

    private string _address;

    public string Address
    {
        get
        {
            return _address;
        }
        set
        {
            _address = value;

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Address"));
            }
        }
    }

    public void UpdateDetails(Member abc)
    {
        abc.FullName = FullName;
        abc.Address = Address;


    }

    public void LoadDetails(Member abc)
    {
        FullName = abc.FullName;
        Address = abc.Address;
    }



     #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    // Used to notify the app that a property has changed.
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}
EddieDuy
  • 61
  • 2
  • 10
  • What did you expect to happen when you said *..but nothing happen*? – har07 Dec 26 '13 at 02:23
  • @har07 I mean the info is not changed as i edited – EddieDuy Dec 26 '13 at 02:58
  • You meant it doesn't changed in the List despite has been edited and saved from detail page? Did you implement INotifyPropertyChanged in Member class? – har07 Dec 26 '13 at 13:15
  • @har07 Yep. That's it. When I use the button instead of the application bar...it work well. I realise that when i use button the event handler is "private void Save_Click(object sender, RoutedEventArgs e)" but with app bar it just is EventArgs instead of RoutedEventArgs... i dont know why – EddieDuy Dec 26 '13 at 22:33
  • and should that different method argument matter? I don't think so. Have you tried to debug? It's hard to tell where the problem is actually, those codes you posted look just fine. If the project is still a small one, you may upload it somewhere so we can help further.. – har07 Dec 27 '13 at 01:22

1 Answers1

1

TextBox in Binding Mode Twoway will not update the source until lost focus happens.

  • If you try to press button, you will find that pressing a button will trigger LostFocus event of text box so the The data will be updated and will be in the correct state before you execute the code in your button.

  • And if you try to press ApplicationBarIconButton you will find that LostFocus didn't fire. So the data will not be updated and will be in old state.

Now how can we overcome this?

Simple you can do one of the following solutions which update source each time text changes

  1. Using Explicit Binding Combined with OnTextChanged from this question

    Explicit: Updates the binding source only when you call the UpdateSource method. It saves you one extra binding set when the user leaves the TextBox.

    in xaml

    <TextBox TextChanged="OnTextBoxTextChanged" Text="{Binding MyText, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
    

    in C#

    private void OnTextBoxTextChanged( object sender, TextChangedEventArgs e )
    {
      TextBox textBox = sender as TextBox;
      // Update the binding source
      BindingExpression bindingExpr = textBox.GetBindingExpression( TextBox.TextProperty );
      bindingExpr.UpdateSource();
    }
    
  2. You can use behavior like the one from this link which listens to TextChanged event and updates the source. I prefer this solution as it is easy to add to your textbox without adding more lines to code behind. All you need to do is to add this lines to your textbox.

    <TextBox x:Name="tbx" Text="{Binding Name, Mode=TwoWay}">
    <i:Interaction.Behaviors>
    <local:UpdateSourceOnTextChangedBehavior />
    </i:Interaction.Behaviors>
    </TextBox>
    

    Don't forget to reference System.Windows.Interactivity also add these namespaces to your page namespace definitions

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
     xmlns:local="name space of the behavior"
    
Community
  • 1
  • 1