简体   繁体   English

WPF ToggleButton.IsChecked绑定不起作用

[英]WPF ToggleButton.IsChecked binding does not work

is there an issue with two way binding to the IsChecked property on a ToggleButton in .NET 3.5? 是否存在双向绑定到.NET 3.5中的ToggleButton上的IsChecked属性的问题?

I have this XAML: 我有这个XAML:

 <ToggleButton 
                    Name="tbMeo"
                    Command="{Binding FilterOnSatelliteTypeCmd}" 
                    IsChecked="{Binding ShowMeoDataOnly, Mode=TwoWay}"
                    ToolTip="Show MEO data only">
                    <Image Source="../images/32x32/Filter_Meo.png" Height="16" />
                </ToggleButton>

I have a ViewModel with the following property: 我有一个具有以下属性的ViewModel:

 private bool _showMeoDataOnly;
    public bool ShowMeoDataOnly
    {
        get { return _showMeoDataOnly; }
        set
        {
            if (_showMeoDataOnly != value)
            {
                _showMeoDataOnly = value;
                RaisePropertyChangedEvent("ShowMeoDataOnly");
            }
        }
    }

If I click on the ToggleButton, the value of ShowMeoDataOnly is set accordingly. 如果我单击ToggleButton,则相应地设置ShowMeoDataOnly的值。 However, if I set ShowMeoDataOnly to true from code behind, the ToggleButton's visual state does not change to indicate that IsChecked is true. 但是,如果我从后面的代码中将ShowMeoDataOnly设置为true,则ToggleButton的可视状态不会更改以指示IsChecked为true。 However, if I manually set the ToggleButton's IsChecked property instead of setting ShowMeoDataOnly to true in code behind, the button's visual state changes accordingly. 但是,如果我手动设置ToggleButton的IsChecked属性而不是在后面的代码中将ShowMeoDataOnly设置为true,则按钮的可视状态会相应地更改。

Unfortunately, switching over to .NET 4/4.5 is not an option right now, so I cannot confirm if this is a .NET 3.5 problem. 不幸的是,切换到.NET 4 / 4.5现在不是一个选项,所以我无法确认这是否是.NET 3.5问题。

Is there anything wrong with my code? 我的代码有什么问题吗?

Using a .NET 3.5 project to test this and the binding seems to work for me. 使用.NET 3.5项目来测试这个并且绑定似乎对我有用。 Do you have INotifyPropertyChanged implemented on your ViewModel and use it appropriately when ShowMeoDataOnly gets set? 您是否在ViewModel上实现了INotifyPropertyChanged并在ShowMeoDataOnly设置时正确使用它? You didn't post all your code, so it's hard to tell what the ViewModel is doing. 您没有发布所有代码,因此很难说出ViewModel正在做什么。

Here's what I have that worked. 这就是我的工作。 When I run the application, the button is selected. 当我运行应用程序时,按钮被选中。 That's because ViewModelBase implements INotifyPropertyChanged and I do base.OnPropertyChanged("ShowMeoDataOnly") when the property is set. 这是因为ViewModelBase实现了INotifyPropertyChanged并且在设置属性时执行base.OnPropertyChanged("ShowMeoDataOnly")

MainWindow.xaml MainWindow.xaml

<Window x:Class="ToggleButtonIsCheckedBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ToggleButtonIsCheckedBinding"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <ToggleButton IsChecked="{Binding ShowMeoDataOnly, Mode=TwoWay}">
            Show Meo Data Only
        </ToggleButton>
    </Grid>
</Window>

MainWindowViewModel.cs MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ToggleButtonIsCheckedBinding
{
    class MainWindowViewModel : ViewModelBase
    {
        bool _showMeoDataOnly;
        public bool ShowMeoDataOnly {
            get
            {
                return _showMeoDataOnly;
            }

            set
            {
                _showMeoDataOnly = value;
                base.OnPropertyChanged("ShowMeoDataOnly");
            }
        }

        public MainWindowViewModel()
        {
            ShowMeoDataOnly = true;
        }
    }
}

ViewModelBase.cs ViewModelBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;

namespace ToggleButtonIsCheckedBinding
{
    /// <summary>
    /// Base class for all ViewModel classes in the application.
    /// It provides support for property change notifications 
    /// and has a DisplayName property.  This class is abstract.
    /// </summary>
    public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
    {
        #region Constructor

        protected ViewModelBase()
        {
        }

        #endregion // Constructor

        #region DisplayName

        /// <summary>
        /// Returns the user-friendly name of this object.
        /// Child classes can set this property to a new value,
        /// or override it to determine the value on-demand.
        /// </summary>
        public virtual string DisplayName { get; protected set; }

        #endregion // DisplayName

        #region Debugging Aides

        /// <summary>
        /// Warns the developer if this object does not have
        /// a public property with the specified name. This 
        /// method does not exist in a Release build.
        /// </summary>
        [Conditional("DEBUG")]
        [DebuggerStepThrough]
        public void VerifyPropertyName(string propertyName)
        {
            // Verify that the property name matches a real,  
            // public, instance property on this object.
            if (TypeDescriptor.GetProperties(this)[propertyName] == null)
            {
                string msg = "Invalid property name: " + propertyName;

                if (this.ThrowOnInvalidPropertyName)
                    throw new Exception(msg);
                else
                    Debug.Fail(msg);
            }
        }

        /// <summary>
        /// Returns whether an exception is thrown, or if a Debug.Fail() is used
        /// when an invalid property name is passed to the VerifyPropertyName method.
        /// The default value is false, but subclasses used by unit tests might 
        /// override this property's getter to return true.
        /// </summary>
        protected virtual bool ThrowOnInvalidPropertyName { get; private set; }

        #endregion // Debugging Aides

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Raised when a property on this object has a new value.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The property that has a new value.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            this.VerifyPropertyName(propertyName);

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        #endregion // INotifyPropertyChanged Members

        #region IDisposable Members

        /// <summary>
        /// Invoked when this object is being removed from the application
        /// and will be subject to garbage collection.
        /// </summary>
        public void Dispose()
        {
            this.OnDispose();
        }

        /// <summary>
        /// Child classes can override this method to perform 
        /// clean-up logic, such as removing event handlers.
        /// </summary>
        protected virtual void OnDispose()
        {
        }

#if DEBUG
        /// <summary>
        /// Useful for ensuring that ViewModel objects are properly garbage collected.
        /// </summary>
        ~ViewModelBase()
        {
            string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode());
            System.Diagnostics.Debug.WriteLine(msg);
        }
#endif

        #endregion // IDisposable Members
    }
}

(Note: ViewModelBase is pulled from this project: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx ) (注意:ViewModelBase来自此项目: http//msdn.microsoft.com/en-us/magazine/dd419663.aspx

Verify that you DataContext is set up correctly. 验证您是否正确设置了DataContext。

DataContext = this;

... in your MainWindow.xaml.cs constructor is the easiest way, assuming the code we're looking at is in the MainWindow class. ...在MainWindow.xaml.cs构造函数中是最简单的方法,假设我们正在查看的代码是在MainWindow类中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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