WPF ToggleButton.IsChecked 绑定不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13147086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ToggleButton.IsChecked binding does not work
提问by Klaus Nji
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. 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.
如果我单击 ToggleButton,则 ShowMeoDataOnly 的值会相应地设置。但是,如果我从后面的代码中将 ShowMeoDataOnly 设置为 true,则 ToggleButton 的视觉状态不会更改以指示 IsChecked 为 true。但是,如果我手动设置 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?
我的代码有什么问题吗?
采纳答案by Kyle Tolle
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.
使用 .NET 3.5 项目来测试这个,绑定似乎对我有用。您是否在 ViewModel 上实现了 INotifyPropertyChanged 并在设置 ShowMeoDataOnly 时正确使用它?您没有发布所有代码,因此很难判断 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
主窗口.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
主窗口视图模型.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)
(注意:ViewModelBase 是从这个项目中提取的:http: //msdn.microsoft.com/en-us/magazine/dd419663.aspx)
回答by Evil Closet Monkey
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 类中。