0

So in my WPF app, I am trying to figure out how to make this scenario as MVVM:

  1. Input text in a TextBox;
  2. On a button press, retrieve the input and pass it to a function that is for a command

I have tried doing something along the lines of this:

private string creatureName;
public string CreatureName
{
    get { 
        return creatureName; 
    }
    set
    {
        if(!string.Equals(creatureName, value))
        {
            creatureName = value;
            OnPropertyChanged("CreatureName");
        }
    }
}

and textbox like this:

<TextBox x:Name="CreatureNameBox" Text="{Binding Path=CreatureName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" TextWrapping="NoWrap" FontFamily="Century Gothic" FontSize="16" Margin="150,0,150,16" MaxLines="1" Height="26" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="5,3,5,3" MaxLength="100"/>

but it didn't work so I removed it.

Below is my code, if more code is needed let me know & I will update the ticket

TextBox:

<TextBox x:Name="CreatureNameBox" TextWrapping="NoWrap" FontFamily="Century Gothic" FontSize="16" Margin="150,0,150,16" MaxLines="1" Height="26" HorizontalAlignment="Stretch" VerticalAlignment="Center" Padding="5,3,5,3" MaxLength="100"/>

Button: Command is CreateNewCreature

<StackPanel>
     <Button x:Name="CreateButton" Content="Create" FontWeight="Bold" FontFamily="Century Gothic" FontSize="18" Margin="10,3,10,0" Padding="0,5,0,5" Command="{Binding CreateNewCreature}" Height="34"/>
</StackPanel>

ViewModel: NewCreature() is where I want to pass the input value to as a string

namespace Creator.ViewModels
{
    public class CreatureCreatorViewModel : ViewModelBase, INotifyPropertyChanged
    {
        public CreatureModel CreateNewCreature { get; set; }

        public CreatureCreatorViewModel(NavigationStore navigationStore)
        {
            CreateNewCreature = new CreatureModel().NewCreature(*Retrieved TextBoxInput here*);
        }

        public CreatureCreatorViewModel()
        {
        }
    }
}

Model:

namespace Creator.Models
{
    public class CreatureModel : ISerializable
    {
        public string Name { get; set; }

        public CreatureModel() { }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Name", Name);
        }

        public CreatureModel NewCreature(string creatureName)
        {
            CreatureModel newCreature = new CreatureModel
            {
                Name = creatureName
            };

            using (FileStream fs = File.Open("[Censored Directory]/Data/TEST.5e", FileMode.Create))
            {
                Byte[] info = new UTF8Encoding(true).GetBytes("Name : " + newCreature.Name);
                fs.Write(info);
            }

            return newCreature;
        }

        public CreatureModel(SerializationInfo info, StreamingContext context)
        {
            Name = (string)info.GetValue("Name", typeof(string));
        }
    }
}
  • There's no binding on the TextBox Text property to the CreatureName property? – Ryan Thomas Apr 16 '21 at 19:20
  • Yeah, it used to have this binding Text="{Binding Path=CreatureName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" but i removed it, when the last attempt didnt work – Rihards Krastiņš Apr 16 '21 at 19:25
  • Your button command isn't a command, that will not work. – Trevor Apr 16 '21 at 19:27
  • @RihardsKrastiņš Where is that property in the ViewModel or the CreatureModel? It may need to be CreateNewCreature.CreatureName, however I am very confused as to why you're creating a new create in the constructor. – Ryan Thomas Apr 16 '21 at 20:11
  • @RyanThomas I just want to know how to implement retrieval of textbox input and pass it to a function in my current code. The sample code doesn't have anything for that functionality as I haven't found a proper way to implement it. – Rihards Krastiņš Apr 17 '21 at 08:16

1 Answers1

0

For the simplest case. ViewModel:

public class FunctionViewModel : BaseInpc
{
    private int? _functionValue;
    public int? FunctionValue { get => _functionValue; set => Set(ref _functionValue, value); }


    private RelayCommand _functionCommand;
    public RelayCommand FunctiontCommand => _functionCommand
        ?? (_functionCommand = new RelayCommand<string>(FunctionExecute));

    private void FunctionExecute(string parameter)
    {
        //Some function is calculated here from received parameter.
        //For example, just the length of the string.

        FunctionValue = parameter?.Length;
    }
}

XAML:

<UniformGrid DataContext="{DynamicResource viewModel}" Columns="2">
    <FrameworkElement.Resources>
        <local:FunctionViewModel x:Key="viewModel"/>
    </FrameworkElement.Resources>
    <TextBox x:Name="textBox" VerticalAlignment="Center" Margin="5" HorizontalContentAlignment="Center"/>
    <Button Content="Calculate function" Padding="15 5" VerticalAlignment="Center"
            Command="{Binding FunctiontCommand, Mode=OneWay}"
            CommandParameter="{Binding Text, ElementName=textBox}"/>
    <TextBlock Text="Function value:" HorizontalAlignment="Right" Margin="5"/>
    <TextBox Text="{Binding FunctionValue}" IsReadOnly="True" VerticalAlignment="Top" Margin="5"
             HorizontalContentAlignment="Center"/>
</UniformGrid>

The base classes from this answer were used: https://stackoverflow.com/questions/63174956/wpf-update-button-if-text-in-textbox-changes/63179286?r=SearchResults&s=1|42.4027#63179286

EldHasp
  • 6,079
  • 2
  • 9
  • 24
  • Where does the FunctionExecute come from? I don't see it here nor in the link – Rihards Krastiņš Apr 17 '21 at 17:17
  • The FunctionExecute method is called when you click on the button to which the FunctiontCommand is binding. This is a typical WPF mechanism. The method is injected into the command when the command is initialized: `new RelayCommand(FunctionExecute)`. – EldHasp Apr 17 '21 at 19:04