简体   繁体   中英

data not updated properly through DataBinding (C#, .NET Framework 4.7.2)

I am trying to write a WPF application that takes an user input in one UserControl and then shows it in another UserControl, on a different Page. To capture user input in SetupLocation, I use a TextBox which has a TwoWay binding to a LocationSettings object, which currently has only one attribute, LocationName. The other Page includes an UserControl called ShowResult, and it has a OneWay binding to the LocationSettings object.

I am using .NET Framework v4.7.2 and Visual Studio 2019.

However:

  1. the value entered in SetupLocation never shows in the result page (the result page shows whatever default value I choose to assign to LocationName in the constructor for LocationSettings).
  2. the value entered in SetupLocation is preserved regardless if I press "Set" button, or not. It seems that UpdateSourceTrigger parameter is ignored, as I had exactly same result when I used LostFocus as a parameter for UpdateSourceTrigger.

What am I missing?

This is the XAML for UserControl called SetupLocation (used to input the data):

<StackPanel Orientation="Vertical" Margin="10"
            VerticalAlignment="Top">
    <StackPanel.Resources>
        <ObjectDataProvider x:Key="locationInput" ObjectType="{x:Type classes:LocationSettings}"/>
    </StackPanel.Resources>
    <TextBox x:Name="LocationName" 
        <TextBox.Text>
            <Binding Source="{StaticResource locationInput}"
                     Path="LocationName"
                     Mode="TwoWay"
                     UpdateSourceTrigger="Explicit"/>
        </TextBox.Text>
    </TextBox>
    <Button x:Name="addParameters"  
            Content="Set"
            Click="addParameters_Click"/>
</StackPanel>

Code behind for SetupLocation:

    public partial class SetupLocation : UserControl
    {
        public SetupLocation()
        {
            InitializeComponent();
        }

        private void addParameters_Click(object sender, RoutedEventArgs e)
        {
            BindingExpression be = LocationName.GetBindingExpression(TextBox.TextProperty);
            be.UpdateSource();
        }
    }

The XAML for UserControl (part of a different Page than SetupLocation) ShowResult that should show what was entered in the SetupLocation:

<StackPanel>
    <StackPanel.Resources>
        <ObjectDataProvider x:Key="locationInput" ObjectType="{x:Type classes:LocationSettings}"/>
    </StackPanel.Resources>
    <Label FontSize="18" Foreground="Green">
        <Label.Content>
            <Binding Source="{StaticResource locationInput}"
                          Path="LocationName"
                          />
        </Label.Content>
    </Label>
</StackPanel>

The class LocationSettings that contains the LocationName variable which I need to pass between the two usercontrols.

   public class LocationSettings : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _locationName;
        public string LocationName
        {
            get {
                return _locationName; 
            }
            set {

                _locationName = value;
                OnPropertyChanged();
            }
        }
        
        public LocationSettings()
        {
            // _locationName = "Nowhere really";

        }
        protected void OnPropertyChanged([CallerMemberName] string tmp = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(tmp));
        }
        
    }

MainWindow.xaml:

    public partial class MainWindow : Window
    {
        public LocationSettings DefaultSettings;

        public MainWindow()
        {
            InitializeComponent();
            DefaultSettings = new LocationSettings();
        }

Do you know what the following code using ObjectDataProvider does? It creates an object of type LocationSettings in xaml. Since you do this in both user controls, you create 2 objects (1 in each user control) so each user control is binding to different objects.

<StackPanel.Resources>
    <ObjectDataProvider x:Key="locationInput" ObjectType="{x:Type classes:LocationSettings}"/>
</StackPanel.Resources>

As a possible solution, I am assuming your MainWindow hosts both user controls. If this is the case, set the DataContext of your main window to the LocationSettings you create in the constructor rather than using an ObjectDataProvider in the user controls. The parent (your MainWindow ) data context will be inherited by both user controls.

public partial class MainWindow : Window
{
    // I changed this to a "getter".
    // The way you declared it would make it a public "field" and not a "property"
    public LocationSettings DefaultSettings { get; }

    public MainWindow()
    {
        InitializeComponent();
        DefaultSettings = new LocationSettings();
        DataContext = DefaultSettings;  // Set the data context of the main window
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM