简体   繁体   中英

Silverlight:TextBox is not updating, PropertyChangedEventHandler is null

I have a project that has among other things TextBox and button which loads a text file into string which is binded to TextBox Text property.

Code: In my MainPage.xaml

<Grid Grid.Column="0" Grid.Row="1">
 <Grid.DataContext>
  <local:ViewModel/>
 </Grid.DataContext>
<Grid.RowDefinitions>
 <RowDefinition Height="25"/>
 <RowDefinition/>
 <RowDefinition Height="30"/>
</Grid.RowDefinitions>
 <TextBox Grid.Row="1" Margin="5,5,5,5" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" Text="{Binding CardsList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

 <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="5,0,0,0" >
  <Button Content="Wczytaj Plik" Command="{Binding LoadTextFile}"/>
  <Button Content="Wyczyść Listę"></Button>
 </StackPanel>
</Grid>

My ViewModel:

public class ViewModel : ObservableObject
{

    private static bool _dateIsNotChecked;
    private static string _cardsList;        
    public static ICommand LoadTextFile { get; set; }
    private OpenFileDialog textOpenFileDialog;

    #region Properties
    public string CardsList
    {
        get
        {
            return _cardsList;
        }
        set
        {
            _cardsList = value;
            RaisePropertyChanged("_cardsList"); //It was CardList - still doesn't work
        }
    }

    public bool DateIsNotChecked
    {
        get
        {
            return _dateIsNotChecked;
        }

    }

    public bool DateIsChecked
    {
        get
        {
            return !_dateIsNotChecked;
        }
        set
        {
            _dateIsNotChecked = !value;
            RaisePropertyChanged("DateIsNotChecked");

        }
    }
    #endregion Properties

    public ViewModel()
    {
        if (CardsList == null)
        {
            CardsList = "";

            _dateIsNotChecked = false;
            LoadTextFile=new DelegateCommand(LoadTextFileExecute, CanLoadTextFileExecute);
            emmDialog = new SaveFileDialog { Filter = "Emm Files | *.emm", DefaultExt = "emm" };
            textOpenFileDialog = new OpenFileDialog{Filter="TXT Files|*.txt"};
        }
    }


    #region Commands 

    void CreateEmmFileExecute(object param)
    {
        var emmFileText = new EmmCreator(Message, Duration, Date, RepeatCount, RepeatDuration, CardsList.Split(new string[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries).ToList());

        if (emmDialog.ShowDialog() != true) return;
        using (var temp = new StreamWriter(emmDialog.OpenFile()))
        {

                temp.Write(emmFileText.EmmFile);
        }
    }

    bool CanCreateEmmFileExecute(object param)
    {
        return true;
    }

    void LoadTextFileExecute(object param)
    {
        //CardsList = "2";
        if (textOpenFileDialog.ShowDialog() != true)
            return;
        using (var temp = new StreamReader(textOpenFileDialog.File.OpenRead()))
        {
            CardsList = CardsList + temp.ReadToEnd();
        }

    }

    bool CanLoadTextFileExecute(object param)
    {
        return true;
    }


    #endregion Commands



}

DelegateCommand:

public class DelegateCommand : ICommand
    {
        /// <summary>
        /// Occurs when changes occur that affect whether the command should execute.
        /// </summary>
        public event EventHandler CanExecuteChanged;

        Func<object, bool> canExecute;
        Action<object> executeAction;
        bool canExecuteCache;

        /// <summary>
        /// Initializes a new instance of the <see cref="DelegateCommand"/> class.
        /// </summary>
        /// <param name="executeAction">The execute action.</param>
        /// <param name="canExecute">The can execute.</param>
        public DelegateCommand(Action<object> executeAction,
                               Func<object, bool> canExecute)
        {
            this.executeAction = executeAction;
            this.canExecute = canExecute;
        }

        #region ICommand Members
        /// <summary>
        /// Defines the method that determines whether the command 
        /// can execute in its current state.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. 
        /// If the command does not require data to be passed,
        /// this object can be set to null.
        /// </param>
        /// <returns>
        /// true if this command can be executed; otherwise, false.
        /// </returns>
        public bool CanExecute(object parameter)
        {
            bool tempCanExecute = canExecute(parameter);

            if (canExecuteCache != tempCanExecute)
            {
                canExecuteCache = tempCanExecute;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, new EventArgs());
                }
            }

            return canExecuteCache;
        }

        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. 
        /// If the command does not require data to be passed, 
        /// this object can be set to null.
        /// </param>
        public void Execute(object parameter)
        {
            executeAction(parameter);
        }
        #endregion
    }

And my ObservableObject:

public abstract class ObservableObject : INotifyPropertyChanged
    {


        public  event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
        {
            var propertyName = PropertySupport.ExtractPropertyName(propertyExpresssion);
            this.RaisePropertyChanged(propertyName);
        }

        protected void RaisePropertyChanged(string propertyName)
        {
            //VerifyPropertyName(propertyName);
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }

As you can see I've also have for instance a "DateIsNotChecked" property which is binded to checkbox and DatePicker and it works.. By debugging I've come to conclusion that when "CardsList" is updated PropertyChanged event in "ObservableObject" is equal null which is why it's not updating binding. And unfortunately i don't know why, could someone please point me my mistake, please?;)

Thanks for your help:)

Try:

RaisePropertyChanged("CardsList"); 

You must raise the property changed on the Property which the textbox is bound to. In other words, the public property, not the private backer.

Also, try setting TextWrapping = TextWrapping.Wrap in your textbox.

Next, try debugging: Set a breakpoint on

LoadTextFileExecute

and step through it and make sure it is doing everything you want.

Also try putting a breakpoint on the setter of CardsList to make sure it is getting set as expected.

Greg

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