Enable button based on TextBox value (WPF)

后端 未结 6 1606
無奈伤痛
無奈伤痛 2021-02-06 02:53

This is MVVM application. There is a window and related view model class.

There is TextBox, Button and ListBox on form. Button is

相关标签:
6条回答
  • 2021-02-06 03:06

    Things look much clearer now with the edits, thanks! This might be a stupid question (I'm somewhat tired of a long day's work), but why don't you bind to the command directly, instead of through a static resource?

    <Button Command="{Binding AddObjectCommand}">Add</Button>
    
    0 讨论(0)
  • 2021-02-06 03:11

    Try raising CanExecuteChanged when your property changes. The command binding is really distinct from the property binding and buttons bound to commands are alerted to a change in status by the CanExecuteChanged event.

    In your case, you could fire a check when you do the PropertyChanged on the bound property that would evaluate it and set the command's internal CanExecute flag and then raise CanExecuteChanged. More of a "push" into the ICommand object than a "pull".

    0 讨论(0)
  • 2021-02-06 03:17

    Since you are using the DelegateCommand, you can call it's RaiseCanExecuteChanged method when your text property changes. I'm not sure what you are trying to accomplish with your CommandReference resource, but typically you just bind the commands directly to the button element's Command property:

    <TextBox Text="{Binding ObjectName, UpdateSourceTrigger=ValueChanged}" />
    <Button Command="{Binding AddObjectCommand}" Content="Add" />
    

    This would be the relevant portion of your view model:

    public string ObjectName
    {
        get { return objectName; }
        set
        {
            if (value == objectName) return;
            value = objectName;
            AddObjectCommand.RaiseCanExecuteChanged();
            OnPropertyChanged("ObjectName");
        }
    }
    
    0 讨论(0)
  • 2021-02-06 03:17

    If ElementName binding does not work, use:

    <Entry x:Name="Number1" Text="{Binding Number1Text}" Keyboard="Numeric"></Entry>
    <Entry x:Name="Number2" Text="{Binding Number2Text}" Keyboard="Numeric"></Entry>
    <Button Text="Calculate" x:Name="btnCalculate" Command="{Binding CalculateCommand}" IsEnabled="{Binding Source={x:Reference Number1, Number2}, Path=Text.Length, Mode=OneWay}"></Button>

    or use:

    <Entry x:Name="Number1" Text="{Binding Number1Text}" Placeholder="Number 1" Keyboard="Numeric"></Entry>
    <Entry x:Name="Number2" Text="{Binding Number2Text}" Placeholder="Number 2" Keyboard="Numeric"></Entry>
    
    <Button VerticalOptions="Center" Text="Calculate" x:Name="btnCalculate" Command="{Binding CalculateCommand}">
    <Button.Triggers>
      <DataTrigger TargetType="Button"
                   Binding="{Binding Source={x:Reference Number1, Number2},
                                     Path=Text.Length}"
                   Value="{x:Null}">
          <Setter Property="IsEnabled" Value="False" />
      </DataTrigger>
    </Button.Triggers>

    0 讨论(0)
  • 2021-02-06 03:21

    Echoing Abe here, but the "right" path to take here is using:

    public void RaiseCanExecuteChanged();
    

    exposed on DelegateCommand. As far as dependencies go, I don't think you're really doing anything "bad" by raising this when the property that the command depends on changes within the ViewModel. In that case, the coupling is more or less contained wholly within the ViewModel.

    So, taking your above example, in your setter for "ObjectName", you would call RaiseCanExecuteChanged on the command "AddObjectCommand".

    0 讨论(0)
  • I know this is an old question but I personally think it's easier to bind the textbox Length to button's IsEnabled property, e.g.:

    <TextBox Name="txtbox" Width="100" Height="30"/>
    <Button Content="SomeButton " Width="100" Height="30" 
    
      IsEnabled="{Binding ElementName=txtbox, Path=Text.Length, Mode=OneWay}"></Button>
    
    0 讨论(0)
提交回复
热议问题