Question La liaison bidirectionnelle WPF ne fonctionne pas


J'ai un contexte de données (UserPreferences) affecté à ma fenêtre principale et à une zone de texte qui se lie à une propriété dans l'une des propriétés du contexte de données (CollectionDevice) dans le contexte.

Lorsque la fenêtre est chargée, celle-ci ne lie pas les propriétés de mon modèle. Je vérifie dans le débogueur que le contexte de données est défini sur l'objet modèle et que les propriétés du modèle sont correctement affectées. Tout ce que je reçois cependant, c’est une série de textbox avec des 0.

Lorsque j'entre les données dans la zone de texte, les données sont mises à jour dans le modèle. Le problème se produit simplement lorsque je charge les données et que je les applique au contexte de données, la zone de texte n'est pas mise à jour.

Lorsque je sauvegarde le modèle dans la base de données, les données appropriées sont enregistrées dans la zone de texte. Lorsque je restaure le modèle à partir de la base de données, les données appropriées sont appliquées. Lorsque le modèle est appliqué au contexte de données dans mon constructeur, le contexte de la zone de texte contient les données correctes et ses propriétés sont affectées comme il se doit. Le problème est que l'interface utilisateur ne reflète pas cela.

XAML

<Window.DataContext>
    <models:UserPreferences />
</Window.DataContext>

        <!-- Wrap pannel used to store the manual settings for a collection device. -->
        <StackPanel Name="OtherCollectionDevicePanel">
            <StackPanel Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center" Margin="10, 10, 0, 0" Text="Baud Rate" />
                <TextBox Name="BaudRateTextBox" Text="{Binding Path=SelectedCollectionDevice.BaudRate, Mode=TwoWay}" Margin="10, 10, 0, 0" MinWidth="80" ></TextBox>
            </StackPanel>
            <WrapPanel>
                <TextBlock VerticalAlignment="Center" Margin="10, 10, 0, 0" Text="Com Port" />
                <TextBox Text="{Binding Path=SelectedCollectionDevice.ComPort, Mode=TwoWay}" Margin="10, 10, 0, 0" MinWidth="80" ></TextBox>
            </WrapPanel>
            <WrapPanel>
                <TextBlock VerticalAlignment="Center" Margin="10, 10, 0, 0" Text="Data Points" />
                <TextBox Text="{Binding Path=SelectedCollectionDevice.DataPoints, Mode=TwoWay}" Margin="10, 10, 0, 0" MinWidth="80" ></TextBox>
            </WrapPanel>
            <WrapPanel Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center" Margin="10, 10, 0, 0" Text="WAAS" />
                <CheckBox IsChecked="{Binding Path=SelectedCollectionDevice.WAAS, Mode=TwoWay}" Content="Enabled" Margin="20, 0, 0, 0" VerticalAlignment="Bottom"></CheckBox>
            </WrapPanel>
        </StackPanel>

Modèle <- Datacontext.

/// <summary>
/// Provides a series of user preferences.
/// </summary>
[Serializable]
public class UserPreferences : INotifyPropertyChanged
{
    private CollectionDevice selectedCollectionDevice;

    public UserPreferences()
    {
        this.AvailableCollectionDevices = new List<CollectionDevice>();

        var yuma1 = new CollectionDevice
        {
            BaudRate = 4800,
            ComPort = 31,
            DataPoints = 1,
            Name = "Trimble Yuma 1",
            WAAS = true
        };

        var yuma2 = new CollectionDevice
        {
            BaudRate = 4800,
            ComPort = 3,
            DataPoints = 1,
            Name = "Trimble Yuma 2",
            WAAS = true
        };

        var toughbook = new CollectionDevice
        {
            BaudRate = 4800,
            ComPort = 3,
            DataPoints = 1,
            Name = "Panasonic Toughbook",
            WAAS = true
        };


        var other = new CollectionDevice
        {
            BaudRate = 0,
            ComPort = 0,
            DataPoints = 0,
            Name = "Other",
            WAAS = false
        };

        this.AvailableCollectionDevices.Add(yuma1);
        this.AvailableCollectionDevices.Add(yuma2);
        this.AvailableCollectionDevices.Add(toughbook);
        this.AvailableCollectionDevices.Add(other);

        this.SelectedCollectionDevice = this.AvailableCollectionDevices.First();
    }

    /// <summary>
    /// Gets or sets the GPS collection device.
    /// </summary>
    public CollectionDevice SelectedCollectionDevice
    {
        get
        {
            return selectedCollectionDevice;
        }
        set
        {
            selectedCollectionDevice = value;
            this.OnPropertyChanged("SelectedCollectionDevice");
        }
    }

    /// <summary>
    /// Gets or sets a collection of devices that can be used for collecting GPS data.
    /// </summary>
    [Ignore]
    [XmlIgnore]
    public List<CollectionDevice> AvailableCollectionDevices { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Notifies objects registered to receive this event that a property value has changed.
    /// </summary>
    /// <param name="propertyName">The name of the property that was changed.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

CollectionDevice <- Où la zone de texte se lie à.

/// <summary>
/// CollectionDevice model
/// </summary>
[Serializable]
public class CollectionDevice : INotifyPropertyChanged
{
    /// <summary>
    /// Gets or sets the COM port.
    /// </summary>
    private int comPort;

    /// <summary>
    /// Gets or sets a value indicating whether [waas].
    /// </summary>
    private bool waas;

    /// <summary>
    /// Gets or sets the data points.
    /// </summary>
    private int dataPoints;

    /// <summary>
    /// Gets or sets the baud rate.
    /// </summary>
    private int baudRate;

    /// <summary>
    /// Gets or sets the name.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// Gets or sets the COM port.
    /// </summary>
    public int ComPort
    {
        get
        {
            return this.comPort;
        }

        set
        {
            this.comPort= value;
            this.OnPropertyChanged("ComPort");
        }
    }

    /// <summary>
    /// Gets or sets the COM port.
    /// </summary>
    public bool WAAS
    {
        get
        {
            return this.waas;
        }

        set
        {
            this.waas = value;
            this.OnPropertyChanged("WAAS");
        }
    }

    /// <summary>
    /// Gets or sets the COM port.
    /// </summary>
    public int DataPoints
    {
        get
        {
            return this.dataPoints;
        }

        set
        {
            this.dataPoints = value;
            this.OnPropertyChanged("DataPoints");
        }
    }

    /// <summary>
    /// Gets or sets the COM port.
    /// </summary>
    public int BaudRate
    {
        get
        {
            return this.baudRate;
        }

        set
        {
            this.baudRate = value;
            this.OnPropertyChanged("BaudRate");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Notifies objects registered to receive this event that a property value has changed.
    /// </summary>
    /// <param name="propertyName">The name of the property that was changed.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public override string ToString()
    {
        return this.Name;
    }
}

Quelqu'un peut me diriger dans la bonne direction? Je suppose que le problème est ma liaison dans XAML; Je ne peux pas le trouver cependant. J'ai besoin qu'il soit bidirectionnel car les données peuvent changer à tout moment pendant la durée de vie des applications dans le modèle (la base de données est mise à jour via des synchronisations) et l'interface utilisateur doit refléter ces changements. l'interface utilisateur

Mise à jour 1

J'ai essayé de forcer la mise à jour de la base de données de la zone de texte, mais cela ne fonctionnait pas aussi bien.

BindingExpression be = this.BaudRateTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();

J'ai aussi essayé de régler le UpdateSourceTrigger à PropertyChanged et cela ne semblait pas non plus résoudre le problème.

<TextBox Name="BaudRateTextBox" Text="{Binding Path=SelectedCollectionDevice.BaudRate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10, 10, 0, 0" MinWidth="80" ></TextBox>

Mise à jour 2

J'ai essayé de suivre avec certains documentation de Microsoft et il ne semble pas résoudre le problème. Les valeurs restent toujours 0 lorsque la fenêtre se charge. La liaison n'est pas mise à jour après la restauration de l'état de l'objet à partir de la base de données. La liaison est câblée, car lorsque j'entre des données, le contexte des données est mis à jour. Pour une raison quelconque, il se comporte comme One-Way quand je l'ai réglé sur deux voies.

Mise à jour 3

J'ai essayé de déplacer le code dans l'événement chargé de la fenêtre et hors du constructeur, mais cela n'a pas semblé aider. Ce que j'ai trouvé intéressant, c'est que l'événement PropertyChanged ne soit pas déclenché pendant le processus de désérialisation. Je ne pense pas que cela soit important dans ce cas, car l'objet est entièrement restauré correctement, puis je l'attribue au contexte de données. J'ai déplacé le contexte de données hors du XAML et dans le WindowLoaded afin de tester si le XAML était le problème. Le résultat était le même.

private void WindowLoaded(object sender, RoutedEventArgs e)
{
    // Restore our preferences state.
    var preferences = new UserPreferenceCommands();
    Models.UserPreferences viewModel = new Models.UserPreferences();

    // Set up the event handler before we deserialize.
    viewModel.PropertyChanged += viewModel_PropertyChanged;
    preferences.LoadPreferencesCommand.Execute(viewModel);

    // At this point, viewModel is a valid object. All properties are set correctly.
    viewModel = preferences.Results;

    // After this step, the UI still shows 0's in all of the text boxs. Even though the values are not zero.
    this.DataContext = viewModel;
}

// NEVER gets fired from within the WindowLoaded event.
void viewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    MessageBox.Show("Property changed!");
}

// This changes the model properties and is immediately reflected in the UI. Why does this not happen within the WindowLoaded event?
private void TestButtonClickEvent(object sender, RoutedEventArgs e)
{
    var context = this.DataContext as Models.UserPreferences;
    context.SelectedCollectionDevice.ComPort = 1536;
}

Mise à jour 4 - Problème identifié 

J'ai identifié le problème, mais j'ai toujours besoin d'une résolution. Le point essentiel de la liaison de données est que je n'ai pas à effectuer cette affectation manuelle. Y a-t-il un problème avec mes implémentations INotify?

private void WindowLoaded(object sender, RoutedEventArgs e)
{
    // Restore our preferences state.
    var preferences = new UserPreferenceCommands();
    Models.UserPreferences viewModel = new Models.UserPreferences();

    // Set up the event handler before we deserialize.
    viewModel.PropertyChanged += viewModel_PropertyChanged;
    preferences.LoadPreferencesCommand.Execute(viewModel);

    // At this point, viewModel is a valid object. All properties are set correctly.
    viewModel = preferences.Results;

    // After this step, the UI still shows 0's in all of the text boxs. Even though the values are not zero.
    this.DataContext = viewModel;

    // SOLUTION: - Setting the actual property causes the UI to be reflected when the window is initialized; setting the actual data context does not. Why? Also note that I set this property and my PropertyChanged event handler still does not fire.
    ((Models.UserPreferences) DataContext).SelectedCollectionDevice = viewModel.SelectedCollectionDevice;

}

9
2018-03-07 14:46


origine


Réponses:


Par défaut, le Text La propriété de TextBox est mise à jour uniquement lorsque le focus est perdu. C'est le comportement par défaut. Avez-vous vérifié avec votre DataContext?

Si vous souhaitez remplacer ce comportement, vous devez inclure la propriété UpdateSourceTrigger de cette façon:

Text="{Binding Path=SelectedCollectionDevice.BaudRate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}

Réglage UpdateSourceTriggerla valeur à PropertyChanged, la modification est reflétée dans la zone de texte lorsque vous modifiez la valeur de votre propriété liée, dès que le texte change.

Un tutoriel utile sur l'utilisation de UpdateSourceTrigger la propriété est ici.


36
2018-03-07 15:12



Bon, j'ai pu déterminer le problème et le résoudre. Cela s'est avéré être une compilation de choses à l'origine de cela.

Tout d'abord, mon modèle.

Préférences de l'utilisateur <- MainWindow est une donnée liée à cela.

[Serializable]
public class UserPreferences : INotifyPropertyChanged
{
    private CollectionDevice selectedCollectionDevice;

    public UserPreferences()
    {
        this.AvailableCollectionDevices = new List<CollectionDevice>();

        var yuma1 = new CollectionDevice
        {
            BaudRate = 4800,
            ComPort = 31,
            DataPoints = 1,
            Name = "Trimble Yuma 1",
            WAAS = true
        };

        var yuma2 = new CollectionDevice
        {
            BaudRate = 4800,
            ComPort = 3,
            DataPoints = 1,
            Name = "Trimble Yuma 2",
            WAAS = true
        };

        var toughbook = new CollectionDevice
        {
            BaudRate = 4800,
            ComPort = 3,
            DataPoints = 1,
            Name = "Panasonic Toughbook",
            WAAS = true
        };


        var other = new CollectionDevice
        {
            BaudRate = 0,
            ComPort = 0,
            DataPoints = 0,
            Name = "Other",
            WAAS = false
        };

        this.AvailableCollectionDevices.Add(yuma1);
        this.AvailableCollectionDevices.Add(yuma2);
        this.AvailableCollectionDevices.Add(toughbook);
        this.AvailableCollectionDevices.Add(other);

        this.SelectedCollectionDevice = this.AvailableCollectionDevices.First();
    }

    /// <summary>
    /// Gets or sets the GPS collection device.
    /// </summary>
    public CollectionDevice SelectedCollectionDevice
    {
        get
        {
            return selectedCollectionDevice;
        }
        set
        {
            selectedCollectionDevice = value;

            if (selectedCollectionDevice.Name == "Other")
            {
                this.AvailableCollectionDevices[3] = value;
            }

            this.OnPropertyChanged("SelectedCollectionDevice");
        }
    }

    /// <summary>
    /// Gets or sets a collection of devices that can be used for collecting GPS data.
    /// </summary>
    [Ignore]
    [XmlIgnore]
    public List<CollectionDevice> AvailableCollectionDevices { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Notifies objects registered to receive this event that a property value has changed.
    /// </summary>
    /// <param name="propertyName">The name of the property that was changed.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Dans le setter pour le SelectedCollectionDevice Je ne cherchais pas à voir si le périphérique sélectionné était autre. Tous les autres périphériques (yuma1, panasonic, etc.) ont des valeurs de propriété prédéterminées qui ne sont jamais modifiées. Lorsque l'utilisateur sélectionne "Autre", les zones de texte sont affichées et peuvent saisir manuellement les données. Le problème était que lorsque les données saisies manuellement étaient restaurées à partir de la base de données lors du chargement de la fenêtre, je n'attribuais pas les données personnalisées dans SelectedCollectionDevice à l'objet correspondant dans la collection.

Pendant le chargement de la fenêtre, le Combobox.SelectedItem a été mis à l'index du SelectedCollectionDevice. le Combobox.ItemsSource a été mis à la AvailableCollectionDevices collection.

this.CollectionDevice.SelectedIndex = 
    viewModel.AvailableCollectionDevices.IndexOf(
        viewModel.AvailableCollectionDevices.FirstOrDefault(
            acd => acd.Name == viewModel.SelectedCollectionDevice.Name));

Lorsque le code ci-dessus est exécuté, la liste déroulante extrait l'objet par défaut de sa source de données, toutes les valeurs étant définies sur zéro. Dans la zone de liste déroulante SelectionChanged événement J'ai attribué le contexte de données SelectedCollectionDevice à la sortie zéro associée à la zone de liste déroulante.

private void CollectionDeviceSelected(object sender, SelectionChangedEventArgs e)
{
    if (e.AddedItems.Count > 0 && e.AddedItems[0] is CollectionDevice)
    {
        // Assign the view models SelectedCollectionDevice to the device selected in the combo box.
        var device = e.AddedItems[0] as CollectionDevice;
        ((Models.UserPreferences)this.DataContext).SelectedCollectionDevice = device;

        // Check if Other is selected. If so, we have to present additional options.
        if (device.Name == "Other")
        {
            OtherCollectionDevicePanel.Visibility = Visibility.Visible;
        }
        else if (OtherCollectionDevicePanel.Visibility == Visibility.Visible)
        {
            OtherCollectionDevicePanel.Visibility = Visibility.Collapsed;
        }
    }
}

Donc longue histoire courte, j'ai ajouté le code ci-dessus dans le setter pour le SelectedCollectionDevice appliquer la valeur à la AvailableCollectionDevices Liste <>. De cette façon, lorsque la combo a la valeur "Autre" sélectionnée, elle extrait la valeur de la collection avec les données correctes. Pendant la désérialisation, je ne fais que désérialiser les SelectedCollectionDevice et non la liste <> qui explique pourquoi les données étaient toujours écrasées lors du premier chargement de la fenêtre.

Cela explique également pourquoi réassigner le contexte de données SelectedCollectionDevice propriété avec le local viewModel.SelectedCollectionDevice travaillait. Je remplaçais l’objet zéro associé à la zone de liste déroulante, qui avait défini le contexte de données lors de la SelectionChanged un événement. Je ne suis pas en mesure de définir le DataContext dans XAML et de supprimer l'affectation manuelle.

Merci pour toute l'aide, cela m'a aidé à réduire mon débogage jusqu'à ce que je finisse par résoudre le problème. Très appréciée!


5
2018-03-07 17:40



Pas une réponse mais je voulais afficher le code qui fonctionne sur ma machine pour aider OP ...

Page xaml complète ...

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <StackPanel Name="OtherCollectionDevicePanel">
            <StackPanel Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center"
                           Margin="10, 10, 0, 0"
                           Text="Baud Rate" />
                <TextBox Name="BaudRateTextBox"
                         Text="{Binding Path=SelectedCollectionDevice.BaudRate, Mode=TwoWay}"
                         Margin="10, 10, 0, 0"
                         MinWidth="80"></TextBox>
            </StackPanel>
            <WrapPanel>
                <TextBlock VerticalAlignment="Center"
                           Margin="10, 10, 0, 0"
                           Text="Com Port" />
                <TextBox Text="{Binding Path=SelectedCollectionDevice.ComPort, Mode=TwoWay}"
                         Margin="10, 10, 0, 0"
                         MinWidth="80"></TextBox>
            </WrapPanel>
            <WrapPanel>
                <TextBlock VerticalAlignment="Center"
                           Margin="10, 10, 0, 0"
                           Text="Data Points" />
                <TextBox Text="{Binding Path=SelectedCollectionDevice.DataPoints, Mode=TwoWay}"
                         Margin="10, 10, 0, 0"
                         MinWidth="80"></TextBox>
            </WrapPanel>
            <WrapPanel Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center"
                           Margin="10, 10, 0, 0"
                           Text="WAAS" />
                <CheckBox IsChecked="{Binding Path=SelectedCollectionDevice.WAAS, Mode=TwoWay}"
                          Content="Enabled"
                          Margin="20, 0, 0, 0"
                          VerticalAlignment="Bottom"></CheckBox>
            </WrapPanel>
            <Button Click="ButtonBase_OnClick" Content="Set ComPort to 11"></Button>
        </StackPanel>
    </Grid>
</Window>

Code complet derrière ...

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Xml.Serialization;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = new UserPreferences();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            ((UserPreferences) DataContext).SelectedCollectionDevice.ComPort = 11;
        }

    }

    /// <summary>
    /// Provides a series of user preferences.
    /// </summary>
    [Serializable]
    public class UserPreferences : INotifyPropertyChanged
    {
        private CollectionDevice selectedCollectionDevice;

        public UserPreferences()
        {
            this.AvailableCollectionDevices = new List<CollectionDevice>();

            var yuma1 = new CollectionDevice
            {
                BaudRate = 4800,
                ComPort = 31,
                DataPoints = 1,
                Name = "Trimble Yuma 1",
                WAAS = true
            };

            var yuma2 = new CollectionDevice
            {
                BaudRate = 4800,
                ComPort = 3,
                DataPoints = 1,
                Name = "Trimble Yuma 2",
                WAAS = true
            };

            var toughbook = new CollectionDevice
            {
                BaudRate = 4800,
                ComPort = 3,
                DataPoints = 1,
                Name = "Panasonic Toughbook",
                WAAS = true
            };


            var other = new CollectionDevice
            {
                BaudRate = 0,
                ComPort = 0,
                DataPoints = 0,
                Name = "Other",
                WAAS = false
            };

            this.AvailableCollectionDevices.Add(yuma1);
            this.AvailableCollectionDevices.Add(yuma2);
            this.AvailableCollectionDevices.Add(toughbook);
            this.AvailableCollectionDevices.Add(other);

            this.SelectedCollectionDevice = this.AvailableCollectionDevices.First();
        }

        /// <summary>
        /// Gets or sets the GPS collection device.
        /// </summary>
        public CollectionDevice SelectedCollectionDevice
        {
            get
            {
                return selectedCollectionDevice;
            }
            set
            {
                selectedCollectionDevice = value;
                this.OnPropertyChanged("SelectedCollectionDevice");
            }
        }

        /// <summary>
        /// Gets or sets a collection of devices that can be used for collecting GPS data.
        /// </summary>
        [XmlIgnore]
        public List<CollectionDevice> AvailableCollectionDevices { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Notifies objects registered to receive this event that a property value has changed.
        /// </summary>
        /// <param name="propertyName">The name of the property that was changed.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    /// <summary>
    /// CollectionDevice model
    /// </summary>
    [Serializable]
    public class CollectionDevice : INotifyPropertyChanged
    {
        /// <summary>
        /// Gets or sets the COM port.
        /// </summary>
        private int comPort;

        /// <summary>
        /// Gets or sets a value indicating whether [waas].
        /// </summary>
        private bool waas;

        /// <summary>
        /// Gets or sets the data points.
        /// </summary>
        private int dataPoints;

        /// <summary>
        /// Gets or sets the baud rate.
        /// </summary>
        private int baudRate;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the COM port.
        /// </summary>
        public int ComPort
        {
            get
            {
                return this.comPort;
            }

            set
            {
                this.comPort = value;
                this.OnPropertyChanged("ComPort");
            }
        }

        /// <summary>
        /// Gets or sets the COM port.
        /// </summary>
        public bool WAAS
        {
            get
            {
                return this.waas;
            }

            set
            {
                this.waas = value;
                this.OnPropertyChanged("WAAS");
            }
        }

        /// <summary>
        /// Gets or sets the COM port.
        /// </summary>
        public int DataPoints
        {
            get
            {
                return this.dataPoints;
            }

            set
            {
                this.dataPoints = value;
                this.OnPropertyChanged("DataPoints");
            }
        }

        /// <summary>
        /// Gets or sets the COM port.
        /// </summary>
        public int BaudRate
        {
            get
            {
                return this.baudRate;
            }

            set
            {
                this.baudRate = value;
                this.OnPropertyChanged("BaudRate");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Notifies objects registered to receive this event that a property value has changed.
        /// </summary>
        /// <param name="propertyName">The name of the property that was changed.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public override string ToString()
        {
            return this.Name;
        }
    }
}

3
2018-03-07 15:30



J'ai eu le même problème. Mon problème était que le nom de la propriété était incorrect. Si vous regardez la fenêtre de sortie, vous pouvez voir toutes les erreurs de liaison lors de l'exécution.

Erreur System.Windows.Data: 40: erreur de chemin BindingExpression:   Propriété 'SelectedProtectedWebsiteTemplate' introuvable sur 'object'   '' ProtectedWebsitesViewModel '(HashCode = 32764015)'.   BindingExpression: Path = SelectedProtectedWebsiteTemplate.Name;   DataItem = 'ProtectedWebsitesViewModel' (HashCode = 32764015); cible   l'élément est 'TextBox' (Name = ''); La propriété target est 'Text' (type   'Chaîne')


0
2018-05-13 04:37