2015-07-31 13 views
9

Mam kontroli zwyczaj wyboru, które stworzyłem z właściwości ICommand i analogicznego własności Bindable (moje pole jest Xamarin.Forms XAML Page), kod jest:Załóż nieruchomość ICommand Bindable na Xamarin Forms

CheckBox.xaml

<Image x:Name="imgCheckBox" 
     WidthRequest="20" 
     HeightRequest="20"/> 

<Label x:Name="lblCheckBox" 
     TextColor="Black" 
     VerticalOptions="CenterAndExpand"/> 

<TapGestureRecognizer Tapped="OnCheckBoxTapped"/> 

CheckBox.xaml.cs

public partial class CheckBox : ContentView 
{ 
    private static ImageSource uncheckedImage; 
    private static ImageSource checkedImage; 

    public CheckBox() 
    { 
     InitializeComponent(); 
     uncheckedImage = ImageSource.FromResource("cbUnchecked.png"); 
     checkedImage = ImageSource.FromResource("cbChecked.png"); 
     imgCheckBox.Source = uncheckedImage; 
    } 

    public static readonly BindableProperty IsCheckedProperty = 
     BindableProperty.Create<CheckBox, bool>(
      checkbox => 
       checkbox.IsChecked, 
       false, 
       propertyChanged: (bindable, oldValue, newValue) => 
       { 
        CheckBox checkbox = (CheckBox)bindable; 
        EventHandler<bool> eventHandler = checkbox.CheckedChanged; 
        if (eventHandler != null) 
        { 
         eventHandler(checkbox, newValue); 
        } 
       });   

    public bool IsChecked 
    { 
     set { SetValue(IsCheckedProperty, value); } 
     get { return (bool)GetValue(IsCheckedProperty); } 
    } 

    void OnCheckBoxTapped(object sender, EventArgs args) 
    { 
     IsChecked = !IsChecked; 
     if (IsChecked) 
     { 
      imgCheckBox.Source = checkedImage; 
     } 
     else 
     { 
      imgCheckBox.Source = uncheckedImage; 
     } 
    } 

    public static readonly BindableProperty CheckBoxCommandProperty = 
     BindableProperty.Create<CheckBox, ICommand>(
     checkbox => 
      checkbox.CheckBoxCommand, 
      null, 
      BindingMode.TwoWay, 
      propertyChanged: (bindable, oldValue, newValue) => 
      { 
       CheckBox checkbox = (CheckBox)bindable; 
       EventHandler<bool> eventHandler = checkbox.CheckedChanged; 
       if (eventHandler != null) 
       { 
        eventHandler(checkbox, checkbox.IsChecked); 
       } 
      }); 

    public event EventHandler<bool> CheckedChanged; 

    public ICommand CheckBoxCommand 
    { 
     get { return (ICommand)GetValue(CheckBoxCommandProperty); } 
     set { SetValue(CheckBoxCommandProperty, value); } 
    } 
} 

realizacja ta opcja jest na innej stronie o nazwie TermsAndConditionsPage, który jest również aa Xamarin.Forms XAML Page, kod realizacji jest:

<toolkit:CheckBox Text="{Binding txtCheckBox}" 
        FontSize="Small" 
        CheckBoxCommand="{Binding OnCheckBoxTapChanged}" 
        IsChecked="{Binding IsCheckedChanged, Mode=TwoWay}"/> 

     <Button Text="Next" 
       Command="{Binding Next_OnClick}" 
       IsEnabled="{Binding Next_IsEnabled}" 
       HorizontalOptions="CenterAndExpand" 
       Clicked="OnNextClicked"/> 

kod związany z ta strona jest pusta (Constructur z InitializeComponent()) . Mam też ViewModel tej strony z tym kodem:

TermsAndConditionsViewModel.cs

private string _txtCheckBox; 
public string txtCheckBox 
{ get { return _txtCheckBox; } 
    set 
    { 
     _txtCheckBox = value; 
     OnPropertyChanged("txtCheckBox"); 
    } 
} 

private bool _Next_IsEnabled; 
public bool Next_IsEnabled 
{ 
    get { return _Next_IsEnabled; } 
    set 
    { 
     _Next_IsEnabled = value; 
     OnPropertyChanged("Next_IsEnabled"); 
    } 
} 

private bool _IsCheckedChanged; 
public bool IsCheckedChanged 
{ 
    get { return _IsCheckedChanged; } 
    set 
    { 
     _IsCheckedChanged = value; 
     OnPropertyChanged("IsCheckedChanged"); 
    } 
} 

public ICommand Next_OnClick { get; set; } 
public ICommand OnCheckBoxTapChanged { get; set; } 

public TermsAndConditionsViewModel() 
{ 
    txtCheckBox = "I agree with the terms and conditions"; 
    Next_OnClick = new Command(NextClicked); 
    OnCheckBoxTapChanged = new Command(CheckBoxTapped); 
} 

private void CheckBoxTapped() 
{ 
    if (IsCheckedChanged) 
    { Next_IsEnabled = true; } 
    else 
    { Next_IsEnabled = false; } 
} 

private void NextClicked() 
{ App.Current.MainPage = new Views.HelloWorld(); } 

#region INPC 
public void OnPropertyChanged(string propertyName) 
{ 
    if (PropertyChanged != null) 
    { PropertyChanged(this, new PropertyChangedEventArgs(propertyName));   }     
} 
public event PropertyChangedEventHandler PropertyChanged; 
#endregion 

Teraz czas pytanie: problem mam jest polecenie CheckBoxTapped nie pracuje, ja to znaczy, nic nie robi, chociaż obraz pola wyboru zmienia się za każdym razem, gdy go dotknę, nie zmienia właściwości Next_IsEnabled mojego przycisku. Chciałbym wiedzieć, czego tu brakuje, aby to polecenie działało poprawnie.

EDIT

Co szukam jest polecenie, które zachowuje się w sposób podobny do tego, który przyciski posiadają.

Dziękuję wszystkim za poświęcony czas!

Odpowiedz

15

Coś w tym stylu (pseudokod):

public class YourClassName : View 
{ 
    public YourClassName() 
    { 
     var gestureRecognizer = new TapGestureRecognizer(); 

     gestureRecognizer.Tapped += (s, e) => { 
      if (Command != null && Command.CanExecute(null)) { 
       Command.Execute(null); 
      } 
     }; 

     var label = new Label(); 
     label.GestureRecognizers.Add(gestureRecognizer); 
    } 

    public static readonly BindableProperty CommandProperty = 
    BindableProperty.Create<YourClassName, ICommand>(x => x.Command, null); 

    public ICommand Command 
    { 
     get { return (ICommand)GetValue(CommandProperty); } 
     set { SetValue(CommandProperty, value); } 
    } 
} 
+2

Dzięki za odpowiedź, to rozwiązać mój problem! –

+0

Dziękuję bardzo! –

13

Od original answer jest już przestarzały, oto nowa metoda:

using System.Windows.Input; 

public partial class MyControl : ContentView 
{ 
    // BindableProperty implementation 
    public static readonly BindableProperty CommandProperty = 
     BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(MyControl), null); 

    public ICommand Command 
    { 
     get { return (ICommand)GetValue(CommandProperty); } 
     set { SetValue(CommandProperty, value); } 
    } 

    // Helper method for invoking commands savely 
    public static void Execute(ICommand command) 
    { 
     if (command == null) return; 
     if (command.CanExecute(null)) 
     { 
      command.Execute(null); 
     } 
    } 

    public MyControl() 
    { 
     InitializeComponent(); 
    } 

    // this is the command that gets bound by the control in the view 
    // (ie. a Button, TapRecognizer, or MR.Gestures) 
    public Command OnTap = new Command(_ => Execute(Command)); 
} 
+0

Dzięki za opublikowanie aktualnej implementacji – Dan

+0

@ MovGP0 Próbowałem wcześniej, ale polecenie nie wiąże. Czy masz działającą próbkę? –

+0

@ MovGP0 Ta próbka rzuciła ten błąd: Inicjator pola nie może odwoływać się do niestatycznego pola, metody lub właściwości "MyControl.Command". Czy możesz mi pomóc? – Hikari

Powiązane problemy