Search code examples
c#wpfmvvmtextbox

Is TextBox string clearing in code behind against MVVM?


I am writing small project to learn MVVM WPF. In the project I am opening with a button dialog window with form to fill up. The form has 2 TextBoxes, that I want to have them empty every time the dialog window is opened again.

enter image description here

In StackOverflow is a lot of examples where TextBox is binded to methods that they are cleaning TextBox with .Clear(); or string.Empty; or .Text=""; etc.

The problem is, that my TextBoxes are already MultiBinded to the converter method used with the form.

       <local:CustomContentDialogBox.CommandParameter>
            <MultiBinding Converter="{StaticResource newPerson}">
                <Binding ElementName="tbID" Path="Text"/>
                <Binding ElementName="tbFirstName" Path="Text"/>
                <Binding ElementName="tbSecondName" Path="Text"/>
                <Binding ElementName="cbHeight" Path="Text" />
            </MultiBinding>
        </local:CustomContentDialogBox.CommandParameter>

As far as I experienced, I was not able to bind it from the texbox by itself again like that:

       <TextBox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2"
                x:Name="tbFirstName"
                FontSize="20" 
                Margin="10,0,0,0" 
                Background="#F5F5F5" 
                TextAlignment="Left"
                Text="{Binding ClearMyBoxPlease}"
                HorizontalAlignment="Left" Height="30" Width="150"/> 

After all day research I figured out, that I can just add to the button in dialog window Click="Button_Click" and clean text boxes in code behind.

<Button Grid.Row="0" Grid.Column="3"
                VerticalAlignment="Top"
                Margin="5,5,5,5"
                Height="30" Width="80"
                FontSize="20"
                Background="#ccffe1"
                Content="Add"
                Click="Button_Click"
                local:CustomContentDialogBox.CustomContentDialogResult="True">
                </Button>

Code behind, where I want clean up only 2 text boxes:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            tbFirstName.Text = "";
            tbSecondName.Text = "";
        }

For your reference, my converter class, that takes TextBoxes from MultiBinding:

public class PersonConverter : IMultiValueConverter
    {
        HeightListToString pzts = new HeightListToString();
        public object Convert(object[] values, Type targetType, object parameter,
        CultureInfo culture)
        {
            string id = (string)values[0];
            string firstName = (string)values[1];
            string secondName = (string)values[2];
            Model.HeightList heightList = (Model.HeightList)pzts.ConvertBack(
            values[3], typeof(Model.HeightList), null, CultureInfo.CurrentCulture);
            return new ViewModel.PersonsList(id, firstName, secondName, heightList);
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
        CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Also I was trying to use ICommand in my ViewModel class and bind it with TextBox. Even if the syntax is wrong, the program was not walking through break points on it:

private ICommand clearMyBoxPlease;

        public ICommand ClearMyBoxPlease
        {
            get
            {
                clearMyBoxPlease = new RelayCommand(
                    argument =>
                    {
                        TextBox tb = (TextBox)argument;
                        tb.Clear();
                    }
                    );
                return clearMyBoxPlease;
            }
        }

My point is, that it is only one code behind that gave me proper effect. The question, is my code against MVVM pattern theory? If yes, what solution should I use? Thanks in advance.

UPDATE:

I just tryed:

<TextBox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2"
                         x:Name="tbFirstName"

                   FontSize="20" 
                   Margin="10,0,0,0" 
                   Background="#F5F5F5" 
                   TextAlignment="Left"  
                   HorizontalAlignment="Left" Height="30" Width="150">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="GotLost">
                            <i:InvokeCommandAction Command="{Binding ClearMyTextPlease}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBox>

with command:

public ICommand ClearMyTextPlease 
        {
            get
            {
                if (clearMyTextPlease == null)
                    clearMyTextPlease = new RelayCommand(
                        argument =>
                        {
                            TextBox tb = (TextBox)argument;
                            tb.Text = string.Empty;
                        }
                        );
                return clearMyTextPlease;
            }
        }

It still does not go through breakpoints on ClearMyTextPlease.


Solution

  • Ok, just for the future reference. I solved my problem with clearing TextBoxes in my dialog window from VM.

    Still I was not able to bind my Text to the property, probably I did something wrong, but I used VisualTreeHelper and called the method before closing the window.

    Method:

    static public void TraverseVisualTree(Visual myMainWindow)
        {
            int childrenCount = VisualTreeHelper.GetChildrenCount(myMainWindow);
            for (int i = 0; i < childrenCount; i++)
            {
                var visualChild = (Visual)VisualTreeHelper.GetChild(myMainWindow, i);
                if (visualChild is TextBox)
                {
                    TextBox tb = (TextBox)visualChild;
                    tb.Clear();
                }
                TraverseVisualTree(visualChild);
            }
        }
    

    Calling in dialg window class in VM:

    public CustomContentDialogBox()
        {
            execute =
            o => //parametr "o" wyrażenia lambda
            {
                if (window == null)
                {
                    window = new Window();
    
                    window.Width = WindowWidth;
                    window.Height = WindowHeight;
                    if (Caption != null) window.Title = Caption;
                    window.Content = WindowContent;
                    //(some logic)
                    TraverseVisualTree(window); 
                    window = null;
                }
            };
        }