WPF ToggleButton.IsChecked绑定不起作用 [英] WPF ToggleButton.IsChecked binding does not work

查看:984
本文介绍了WPF ToggleButton.IsChecked绑定不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NET 3.5中的ToggleButton中,有两种方式绑定到IsChecked属性有问题吗?



我有这个XAML:

 < ToggleButton 
Name =tbMeo
Command ={Binding FilterOnSatelliteTypeCmd}
IsChecked ={Binding ShowMeoDataOnly,Mode = TwoWay}
ToolTip =仅显示MEO数据>
< Image Source =../ images / 32x32 / Filter_Meo.pngHeight =16/>
< / ToggleButton>

我有一个具有以下属性的ViewModel:

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

如果我点击ToggleButton ,相应地设置ShowMeoDataOnly的值。但是,如果我将ShowMeoDataOnly设置为true,则ToggleButton的可视状态不会更改,以指示IsChecked为true。但是,如果我手动设置了ToggleButton的IsChecked属性,而不是在后面的代码中将ShowMeoDataOnly设置为true,则按钮的可视状态将相应地更改。



不幸的是,切换到.NET 4 /4.5现在不是一个选项,所以我无法确认这是否是.NET 3.5问题。



我的代码有什么问题吗?

解决方案

使用.NET 3.5项目来测试这个,绑定似乎对我有用。您的ViewModel上实现了INotifyPropertyChanged,并在ShowMeoDataOnly设置时适当使用它?你没有发布所有的代码,所以很难说明ViewModel正在做什么。



这是我的工作原理。当我运行应用程序时,该按钮被选中。这是因为 ViewModelBase 实现 INotifyPropertyChanged ,我做 base.OnPropertyChanged(ShowMeoDataOnly)当属性设置。



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 =MainWindowHeight =350 Width =525>
< Window.DataContext>
< local:MainWindowViewModel />
< /Window.DataContext>
< Grid>
< ToggleButton IsChecked ={Binding ShowMeoDataOnly,Mode = TwoWay}>
仅显示Meo数据
< / ToggleButton>
< / Grid>
< / Window>

MainWindowViewModel.cs

 使用系统; 
使用System.Collections.Generic;
使用System.Linq;
使用System.Text;

命名空间ToggleButtonIsCheckedBinding
{
class MainWindowViewModel:ViewModelBase
{
bool _showMeoDataOnly;
public bool ShowMeoDataOnly {
get
{
return _showMeoDataOnly;
}

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

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

ViewModelBase.cs

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

命名空间ToggleButtonIsCheckedBinding
{
///< summary>
///应用程序中所有ViewModel类的基类。
///它提供对属性更改通知的支持
///并具有DisplayName属性。这个类是抽象的。
///< / summary>
public abstract class ViewModelBase:INotifyPropertyChanged,IDisposable
{
#region构造函数

protected ViewModelBase()
{
}

#endregion //构造函数

#region DisplayName

///< summary>
///返回此对象的用户友好名称。
///子类可以将此属性设置为新值
///或覆盖它以确定按需的值。
///< / summary>
public virtual string DisplayName {get;保护套}

#endregion // DisplayName

#region调试助手

///< summary>
///如果此对象没有
///具有指定名称的公共属性,则警告开发人员。这个
///方法在Release构建中不存在。
///< / summary>
[Conditional(DEBUG)]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
//验证属性名称是否与真实的,
//这个对象上的public,instance属性。
if(TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg =无效的属性名称:+ propertyName;

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

///< summary>
///返回是否抛出异常,或者如果将无效的属性名称传递给VerifyPropertyName方法,则使用Debug.Fail()
///。
///默认值为false,但单元测试使用的子类可能
///覆盖此属性的getter返回true。
///< / summary>
protected virtual bool ThrowOnInvalidPropertyName {get;私人集合}

#endregion //调试助手

#region INotifyPropertyChanged成员

///< summary>
///当此对象上的属性具有新值时引发。
///< / summary>
public event PropertyChangedEventHandler PropertyChanged;

///< summary>
///引发此对象的PropertyChanged事件。
///< / summary>
///< param name =propertyName>具有新值的属性< / param>
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);

PropertyChangedEventHandler handler = this.PropertyChanged;
if(handler!= null)
{
var e = new PropertyChangedEventArgs(propertyName);
处理程序(这个,e);
}
}

#endregion // INotifyPropertyChanged成员

#region IDisposable会员

///< summary> ;
///当该对象从应用程序
///中删除时调用,并将被收集垃圾。
///< / summary>
public void Dispose()
{
this.OnDispose();
}

///< summary>
///子类可以覆盖此方法来执行
///清理逻辑,例如删除事件处理程序。
///< / summary>
protected virtual void OnDispose()
{
}

#if DEBUG
///< summary>
///有助于确保ViewModel对象被正确的垃圾回收。
///< / summary>
〜ViewModelBase()
{
string msg = string.Format({0}({1})({2})Finalized,this.GetType() .DisplayName,this.GetHashCode());
System.Diagnostics.Debug.WriteLine(msg);
}
#endif

#endregion // IDisposable会员
}
}

(注意:ViewModelBase从此项目中提取: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx


is there an issue with two way binding to the IsChecked property on a ToggleButton in .NET 3.5?

I have this 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:

 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. However, if I set ShowMeoDataOnly to true from code behind, the ToggleButton's visual state does not change to indicate that IsChecked is 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.

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.

Is there anything wrong with my code?

解决方案

Using a .NET 3.5 project to test this and the binding seems to work for me. Do you have INotifyPropertyChanged implemented on your ViewModel and use it appropriately when ShowMeoDataOnly gets set? You didn't post all your code, so it's hard to tell what the ViewModel is doing.

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.

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

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

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 )

这篇关于WPF ToggleButton.IsChecked绑定不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆