web-dev-qa-db-fra.com

La liaison à double sens 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 dans les deux sens à une propriété dans l'une des propriétés du contexte de données (CollectionDevice) dans le contexte. 

Lors du chargement de la fenêtre, les zones de texte ne sont pas liées aux 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 de modèle et que les propriétés du modèle sont correctement affectées. Tout ce que je reçois cependant, ce sont une série de zones de texte avec des zéros.

Lorsque j'entre les données dans la zone de texte, celles-ci sont mises à jour dans le modèle. Le problème se produit 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 j'enregistre 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 données 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>

Model <- 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 est liée.

/// <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 en XAML; Je ne peux pas le trouver cependant. J'ai besoin que ce soit lié dans les deux sens 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 par la synchronisation) et l'interface utilisateur doit refléter ces modifications, mais l'utilisateur peut appliquer les modifications au modèle via l'interface utilisateur.

Mise à jour 1

J'ai essayé de forcer la mise à jour de la zone de texte text-dat, mais cela n'a pas fonctionné aussi bien.

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

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

<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 la documentation de Microsoft et cela ne semble pas résoudre le problème. Les valeurs restent toujours à 0 lors du chargement de la fenêtre. 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 lors de la saisie des données, le contexte des données est mis à jour. Pour une raison quelconque, il agit comme à sens unique quand je l’ai réglé sur Deux voies.

Mise à jour 3

J'ai essayé de déplacer le code dans l'événement window chargé et de le sortir du constructeur, mais cela n'a pas semblé aider. Quelque chose 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 importe dans ce cas car l'objet est entièrement restauré correctement, puis je l'assigne simplement au contexte de données. J'ai déplacé le contexte de données hors du XAML et dans le WindowLoaded afin de vérifier si le problème était dû au XAML. 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 solution. Le point essentiel de la liaison de données est que je n’ai pas à effectuer cette assignation 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;

}
10

Très bien, j'ai pu déterminer le problème et le résoudre. Il s’est avéré qu’il s’agissait d’une compilation des causes de ce problème.

D'abord mon modèle.

UserPreferences <- MainWindow est lié à des données.

[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 configurateur pour SelectedCollectionDevice, je ne cherchais pas à savoir 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 entrer manuellement les données. Le problème était que lorsque les données saisies manuellement ont été 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 de la collection.

Pendant le chargement de la fenêtre, le Combobox.SelectedItem a été défini sur l'index du SelectedCollectionDevice. Le Combobox.ItemsSource a été défini sur la collection AvailableCollectionDevices

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, dans laquelle toutes les valeurs sont définies sur zéro. Au sein de l'événement SelectionChanged de la zone de liste déroulante, j'ai affecté le contexte de données SelectedCollectionDevice à l'élément de sortie nulle associé à 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;
        }
    }
}

En résumé, j'ai ajouté le code ci-dessus dans le configurateur pour le SelectedCollectionDevice afin d'appliquer la valeur à la AvailableCollectionDevices List <>. Ainsi, lorsque la valeur "Autre" est sélectionnée dans la liste déroulante, elle extrait la valeur de la collection avec les données correctes. Lors de la désérialisation, je suis juste en train de désérialiser le SelectedCollectionDevice et non le List <>, raison pour laquelle les données étaient toujours écrasées lors du premier chargement de la fenêtre.

Cela explique également pourquoi la ré-affectation de la propriété SelectedCollectionDevice du contexte de données avec le viewModel.SelectedCollectionDevice local fonctionnait. Je remplaçais l'objet de sortie nulle associé à la zone de liste déroulante, qui avait défini le contexte de données lors de l'événement SelectionChanged. Je ne parviens pas à définir le DataContext dans le XAML et à supprimer l'affectation manuelle.

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

5

Par défaut, la propriété Text de TextBox est mise à jour uniquement lorsque le focus est perdu. L'avez-vous vérifié avec votre DataContext?

Si vous souhaitez remplacer ce comportement, vous devez inclure la propriété UpdateSourceTrigger de la manière suivante:

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

Si vous définissez la valeur de UpdateSourceTrigger sur 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 est modifié.

Un tutoriel utile sur l’utilisation de la propriété UpdateSourceTrigger est here .

42
Alberto Solano

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

Page complète xaml ...

<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
Kevin

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

Erreur System.Windows.Data: 40: Erreur de chemin BindingExpression: Propriété 'SelectedProtectedWebsiteTemplate' non trouvée sur 'objet' '' ProtectedWebsitesViewModel '(HashCode = 32764015)' . BindingExpression: Path = SelectedProtectedWebsiteTemplate.Name; DataItem = 'ProtectedWebsitesViewModel' (HashCode = 32764015); cible l'élément est 'TextBox' (Name = ''); La propriété cible est 'Text' (type 'String')

0
user1546570