2015-11-04 65 views
2

我正試圖將ToggleButton上的「IsChecked」屬性綁定到「ModelView.IsEnabled」。
「ModelView.IsEnabled」始終爲「false」
但按某種方式,ToggleButton仍然可以顯示爲「已選中」。
綁定有什麼問題嗎?
enter image description here切換按鈕雙向綁定不起作用(通用Windows平臺)

XAML

... 
<Page.Resources> 
    <ModelView:ModelView x:Key="ModelView"/> 
</Page.Resources> 
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <ToggleButton IsChecked="{Binding Source={StaticResource ModelView}, Path=IsEnabled, Mode=TwoWay}"> 
     <TextBlock >UWP Toggle Button</TextBlock> 
    </ToggleButton> 
</Grid> 
... 

ModelView.cs

using... 

namespace App2 
{ 
    class ModelView : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     public event EventHandler CanExecuteChanged; 

     private bool _isEnabled; 

     public bool IsEnabled 
     { 
      get { 
       return _isEnabled; 
      } 
      set 
      { 
       _isEnabled = false; 
       OnPropertyChanged("IsEnabled"); 
      } 
     } 

     protected void OnPropertyChanged(string name) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(name)); 
      } 
     } 
    } 
} 
+0

嘗試使代碼'類模型視圖代碼'public class – thumbmunkeys

+0

使'class ModelView'成爲一個公共類仍然沒有正確綁定。:/ ToggleButton仍然會轉爲「已選中」。 – user3863376

+0

你的'set'正在做'_isEnabled = false;'...... – jsanalytics

回答

1

在你的類ModelView,改變IsEnabled從這個:

public bool IsEnabled 
    { 
     get { 
      return _isEnabled; 
     } 
     set 
     { 
      _isEnabled = false; 
      OnPropertyChanged("IsEnabled"); 
     } 
    } 

這樣:

public bool IsEnabled 
    { 
     get { 
      return _isEnabled; 
     } 
     set 
     { 
      _isEnabled = value; 
      OnPropertyChanged("IsEnabled"); 
     } 
    } 

enter image description here

編輯:如果我使用_isEnabled = !value;如你所說,它仍然有效,使用按鈕和狀態現在顯示相反的價值觀:

enter image description here

編輯2:現在,如果你要正確地測試你的綁定,那麼你可以添加一個額外的普通按鈕,這樣做:

private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     myModelView.IsEnabled = !myModelView.IsEnabled; 
    } 

所以你可以單擊Test Button觀看每次truefalse之間的ToggleButton開關。請注意,Test Button不受任何約束,僅用於測試目的。在底部查看相應的XAML。

enter image description here

的問題是,你正在做的方式,「逼迫」 IsEnabled要始終false,你實際上是破壞自己的代碼...:O)

最後,您的代碼在何時何地指定DataContext並不清楚。請看下面如何去做。

XAML:

<Page.DataContext> 
    <local:MyModelView/> 
</Page.DataContext> 

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <ToggleButton x:Name="toggleButton1" Content="ToggleButton" IsChecked="{Binding IsEnabled, Mode=TwoWay}" HorizontalAlignment="Center"/> 
    <TextBlock x:Name="textBlock1" Text="{Binding IsEnabled}" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="126,0,201,286" /> 
    <Button x:Name="button1" Click="button1_Click" Margin="127,400,0,220" Content="Test Button" Height="35" /> 
</Grid> 

代碼隱藏:

private void Page_Loaded(object sender, RoutedEventArgs e) 
    { 
     myModelView = new MyModelView(); 
     this.DataContext = myModelView; 
    } 
+0

謝謝,但那不是我想解決的問題。 我想弄明白爲什麼ToggleButton顯示不同的狀態,然後「ModelView.IsEnabled」。 如果我將'IsEnabled'更改爲'set {_isEnabled =!value; OnPropertyChanged( 「的IsEnabled」); } ToggleButton將處於「ModelView.IsEnabled」的相反狀態。這意味着ToggleButton上的綁定不會反映IsEnabled的值。 – user3863376

+0

請在我的帖子中查看我的編輯2,瞭解如何正確測試您的「ToggleButton」的綁定。你這樣做的方式顯然是錯誤的。你實際上是在破壞你自己的代碼...:O) – jsanalytics

+0

謝謝你的編輯。如果我錯了,請糾正我。那麼在每次clilck之後,'ToggleButton'總是必須從'true到false'或'false to true'? – user3863376

2

試試這個,它的工作對我說: 1。XAML代碼的變化:

<Grid> 
    <Grid.DataContext> 
     <soHelpProject:MainViewModel/> 
    </Grid.DataContext> 
    <ToggleButton IsChecked="{Binding IsToggled, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"> 
     <TextBlock >UWP Toggle Button</TextBlock> 
    </ToggleButton> 
</Grid> 

問候,

+0

確實,它也適用於我。你知道爲什麼嗎? – mamuesstack

0

IsEnabled屬性指示所述用戶能否相互作用與對照。 IsPressed是隻讀屬性。所以IsChecked可能是你需要的。

0

我遇到了同樣的問題,不是ToggleButton,而是TextBox,我想要格式化用戶輸入的文本。

在你的情況下,你想改變你的viewmodel中的IsChecked屬性,並立即反映在用戶界面中(所以總是被取消選中)。你想要的原因絕對不重要。

問題是,如果您點擊ToggleButton,UWP會調用您的屬性的獲取方法,就像您期望的那樣。 ToggleButton的正常操作是從未檢查變爲檢查(反之亦然),這就是你的情況。但是,你期望NotifyPropetyChanged表示UI中的控件。這就是它出錯的地方。當setter執行時(包括NotifyPropertyChanged),getter不會被調用,所以UI並不反映你在setter中做了什麼。 這與TwoWay Binding用來做什麼(並且仍然在WPF中)完全不同。所以你的代碼沒有問題,但似乎綁定機制已經改變了,儘管微軟聲稱它沒有改變。如果你使用x:Bind,它可以正常工作,所以帽子可以解決你的問題。

爲了更清楚地說明一些事情,我已將您的示例稍作修改,以顯示問題。 我已經把頁面上的一個ToggleButton與TwoWay綁定到視圖模型,完全一樣。點擊ToggleButton會將其狀態從已選中狀態切換爲未選中狀態,反之亦然,即使我的viewmodel中的setter始終將該屬性設置爲false(因此未選中)。 但我還添加了一個普通按鈕,我已經綁定到一個命令,該命令還修改了ToggleButton綁定的屬性。點擊此按鈕將調用ToggleButton所綁定的屬性上的setter。當然,setter被調用的方式是一樣的,但在此之後綁定到ToggleButton被調用,因此在這種情況下NotifyPropertyChanged確實會導致UI更新。

如果你使用調試器,你可以看到我的意思。 所以你的問題可以通過使用x:Bind來解決,或者通過另一種方法來更新UI,如果Binding仍然像以前一樣工作,你不應該這麼做。也許微軟已經實施了一些現在破壞了經典綁定的優化。

沒有特別的事情,只是一個MainPage和一個視圖模型。

我對MainPage.xaml中

<Page x:Class="App10.MainPage" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="using:App10" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d"> 
    <Page.Resources> 
     <local:ViewModel x:Key="viewModel" /> 
    </Page.Resources> 

    <Grid x:Name="mainGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
     <StackPanel Margin="10,20,10,0"> 
      <Button 
       x:Name="Button" 
       Content="UWP Normal button" 
       Command="{Binding Source={StaticResource viewModel}, Path=SwitchIschecked}" 
       HorizontalAlignment="Stretch" /> 
      <ToggleButton 
       x:Name="toggleButton" 
       Margin="0,10,0,0" 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Top" 
       IsChecked="{Binding Source={StaticResource viewModel}, Path=IsChecked, 
              Mode=TwoWay}"> 
       <TextBlock>UWP Toggle Button</TextBlock> 

      </ToggleButton> 
     </StackPanel> 
    </Grid> 
</Page> 

代碼爲MainPage.xaml.cs中

using Windows.UI.Xaml.Controls; 

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 

namespace App10 
{ 
    /// <summary> 
    /// An empty page that can be used on its own or navigated to within a Frame. 
    /// </summary> 
    public sealed partial class MainPage : Page 
    { 
     public MainPage() 
     { 
      this.InitializeComponent();  
     }  
    } 
} 

而對於ViewModel.cs

using System; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using System.Windows.Input; 

namespace App10 
{ 
    public class ViewModel : INotifyPropertyChanged 
    { 
     private bool _isChecked; 

     // property for TwoWay binding with ToggleButton 
     public bool IsChecked 
     { 
      get 
      { 
       return _isChecked; 
      } 
      set 
      { 
       // extra var just to check 'value' 
       var _value = value; 
       // now always set it to false 
       _isChecked = false; 
       // Try to pass value of _isChecked to user interface 
       // because there is no check whether the value really 
       // has changed 
       // But this only works if the setter is not being called 
       // directly from the control the property is bound to 
       OnPropertyChanged(); 
      } 
     } 

     private ICommand _switchChecked; 

     // ICommand for normal button, binding to Command 
     // calls method to set Property for ToggleButton 
     public ICommand SwitchIschecked 
     { 
      get 
      { 
       if (_switchChecked == null) 
        _switchChecked = new ChangeChecked(new Action(ChangeVar)); 
       return _switchChecked; 
      } 
      set 
      { 
       _switchChecked = value; 
      } 
     } 

     // This will set the property for the ToggleButton 
     private void ChangeVar() 
     { 
      IsChecked = !IsChecked; 
     } 


     public event PropertyChangedEventHandler PropertyChanged; 

     protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
     { 
      var handler = PropertyChanged; 
      handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 


    } 


    /// <summary> 
    /// Quick class to implement ICommand 
    /// </summary> 
    class ChangeChecked : ICommand 
    { 
     Action _execute; 
     public ChangeChecked(Action execute) 
     { 
      _execute = execute; 
     } 

     public event EventHandler CanExecuteChanged; 

     public bool CanExecute(object parameter) 
     { 
      return true; 
     } 

     public void Execute(object parameter) 
     { 
      _execute(); 
     } 
    } 
} 
+0

對於提出的問題,這似乎是一個很長的答案。是否可以編輯它以提供更簡潔的答案? – Toby

+0

對不起,如果你認爲解釋太長,但顯然問題不明確,所以試圖澄清和解釋除了只提到「使用x:綁定」之外正在發生的事情。這是一個非常普遍的問題,而不僅僅是使用ToggleButton。 – P59