Wpf Caliburn Micro: TextBox getter doesn't return newest value

939 Views Asked by At

I have a very simple sample code, a TextBox and a Button. User inputs some text in textBox and click the Button. It should show a common MessageBox which contains the text he just input in the TextBox.

Problem: the MessageBox shows blank! After some trial and error I found out the reason. I set in .xaml the Focusable of Button as false. Why? Because I want to stop the blinking effect of button after it is clicked once.

So I have an idea. I bind the Focusable to a property in ViewModel and initialized in constructor (or in private field as initial value) of ViewModel as false. Then in the Button-Click event handler before showing MessageBox I set the property to true and then after executing MessageBox set it to false again. Problem: Unfortunately, it doesn't work! It seems the Focusable can only be set once in constructor or in private field as initial value.

Does someone know how to solve this problem? I want to keep the Focusable of the Button to false (to avoid the Button blinking) and I want to get the text from TextBox by clicking the Button. Following is the sample code and feel free to modify and show me the solution. Thank you in advance.

XAML / View

<Grid Width="300" Height="300">
    <StackPanel VerticalAlignment="Center">
        <TextBox Width="150" Text="{Binding Path=MyText}" />
        <Button x:Name="ShowText"
                Width="100"
                Content="Show Text"
                Focusable="{Binding Path=MyFocus}" />
    </StackPanel>
</Grid>

View model

public class ShellViewModel : PropertyChangedBase 
{
    private String _myText;
    public String MyText
    {
        get { return _myText; }
        set
        {
            _myText = value;
            NotifyOfPropertyChange(() => MyText);
        }
    }

    private Boolean _myFocus = false; // if it is true, the MessageBox can show MyText, otherwise MessageBox shows blank
    public Boolean MyFocus
    {
        get { return _myFocus; }
        set
        {
            _myFocus = value;
            NotifyOfPropertyChange(() => MyFocus);
        }
    }

    public void ShowText()
    {
        //MyFocus = true; // this doesn't work
        MessageBox.Show(MyText);
        //MyFocus = false; // this doesn't work
    }
}
1

There are 1 best solutions below

1
On BEST ANSWER
<Grid Width="300" Height="300">
     <StackPanel VerticalAlignment="Center">
        <TextBox Width="150" Text="{Binding MyText, Mode=TwoWay}" />
         <Button x:Name="ShowText"
            Width="100"
            Content="Show Text"
            Focusable="{Binding MyFocus}" />
    </StackPanel> 
</Grid>

or

<Grid Width="300" Height="300">
    <StackPanel VerticalAlignment="Center">
       <TextBox Width="150" x:Name="MyText" />
       <Button x:Name="ShowText"
            Width="100"
            Content="Show Text"
            Focusable="{Binding MyFocus}" />
    </StackPanel>
</Grid>

that should work either way, the way you did the binding wouldn't ever update the underlying property since it wasn't considered bi-directional. Therefore Mode=TwoWay was necessary on the 1st version, the second version uses CM's conventions to find the the textbox and bind it to a property of the same name on the viewmodel.

not sure what blinking your referring to the default style doesn't have a blink... at least not on windows 8.1 or windows 10. The only thing focusable does in the regard of the code frag you did was prevent keyboard access..