简体   繁体   English

WPF MVVM交互将CommandParameter绑定到UI元素

[英]WPF MVVM Interaction Binding CommandParameter to UI element

I want the text in a TextBox to get selected when the TextBox gets focused. 我希望TextBox获得焦点时选择TextBox中的文本。 Therefore I need to binding a Command to the "GotFocus" event. 因此,我需要将命令绑定到“ GotFocus”事件。 The special thing is, that the TextBox is created dynamically via an ItemsControl . 特殊的是,TextBox是通过ItemsControl动态创建 So there is a binding to the UserControl (View), the ItemsControl and the Item itself. 因此,存在对UserControl(视图),ItemsControl和Item本身的绑定。 When I tried to bind the UI element to the CommandParameter I just got the Model bindet to the current item in the ItemsControl. 当我尝试将UI元素绑定到CommandParameter时,我只是将Model绑定绑定到ItemsControl中的当前项目。

All the bindings are working perfectly except the CommandParameter.. 除CommandParameter之外,所有绑定均正常运行。

Somebody got an idea how to get this working? 有人知道如何使它工作?

Here is my code: 这是我的代码:

XAML XAML

/////// <UserControl/> Information:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
x:Name="MainBindingControl"
///////

    <ItemsControl ItemsSource="{Binding MySecondModelList }" Margin="10,10,10,0">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid helper:GridHelper.RowCount="{Binding MyFirstModel.Rows}" helper:GridHelper.ColumnCount="{Binding MyFirstModel.Columns}">
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Grid.Row" Value="{Binding Row}" />
                <Setter Property="Grid.Column" Value="{Binding Column}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Margin="25,25,25,25" Height="30" Width="30" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" TextAlignment="Center" VerticalContentAlignment="Center" >
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="GotFocus">
                            <i:InvokeCommandAction Command="{Binding ElementName=MainBindingControl, Path=DataContext.TextBoxFocusCommand}" CommandParameter="{Binding RelativeSource={ RelativeSource Self }}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                <TextBox.Style>
                    <Style TargetType="TextBox">
                        <Setter Property="Background" Value="OrangeRed" />
                            <Style.Triggers>
                                <Trigger Property="Text" Value="0">
                                    <Setter Property="Background" Value="Orange" />
                                </Trigger>
                                <Trigger Property="Text" Value="1">
                                    <Setter Property="Background" Value="White" />
                                </Trigger>
                                <Trigger Property="Text" Value="2">
                                    <Setter Property="Background" Value="White" />
                                </Trigger>
                                <Trigger Property="Text" Value="3">
                                    <Setter Property="Background" Value="White" />
                                </Trigger>
                                <Trigger Property="Text" Value="4">
                                    <Setter Property="Background" Value="White" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

CS CS

    #region TextBoxFocus
    private ICommand _textBoxFocusCommand;
    public ICommand TextBoxFocusCommand
    {
        get { return _textBoxFocusCommand; }
        set { _textBoxFocusCommand = value; }
    }
    public void TextBoxFocus(object parameter)
    {
        var _tmp = parameter as TextBox;
        if (_tmp != null )
        {
            _tmp.SelectAll();
        }
    }
    #endregion

Models 楷模

public class FirstModel
    {
        public int Rows { get; set; }
        public int Columns { get; set; }
    }

public class SecondModel
    {
        public int Row { get; set; }
        public int Column { get; set; }
        public string Text { get; set; }
    }

public class ViewModel
    {
        public FirstModel MyFirstModel { get; set; }
        public ObservableCollection<SecondModel> MySecondModelList { get; set; }
    }

Since what you want to do is only related to the view, I'd just add the code in the code-behind, instead of trying to use commands and get the TextBox inside the ViewModel. 由于您要执行的操作仅与视图相关,因此,我只是将代码添加到了代码背后,而不是尝试使用命令并在ViewModel中获取TextBox。 In MVVM you should NEVER reference UI assemblies from the ViewModel. 在MVVM中,您永远不要从ViewModel引用UI程序集。 But it is ok for you to use code-behind if what you are trying to do is only related to the View. 但是,如果您要执行的操作仅与视图相关,则可以使用代码隐藏。

So, inside the style of the TextBox, you would have: 因此,在TextBox样式内,您将具有:

<EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>

And then in the code-behind of the UserControl: 然后在UserControl的代码背后:

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    textBox.SelectAll();
}

The complete code of your DataTemplate would then be: 然后,您的DataTemplate的完整代码将是:

<DataTemplate>
    <TextBox Margin="25,25,25,25" Height="30" Width="30" Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" TextAlignment="Center" VerticalContentAlignment="Center" >
        <!-- Just erase this block of code
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="GotFocus">
                <i:InvokeCommandAction Command="{Binding ElementName=MainBindingControl, Path=DataContext.TextBoxFocusCommand}" CommandParameter="{Binding RelativeSource={ RelativeSource Self }}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>-->
        <TextBox.Style>                            
            <Style TargetType="TextBox">
                <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
                <Setter Property="Background" Value="OrangeRed" />
                <Style.Triggers>
                    <Trigger Property="Text" Value="0">
                        <Setter Property="Background" Value="Orange" />
                    </Trigger>
                    <Trigger Property="Text" Value="1">
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                    <Trigger Property="Text" Value="2">
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                    <Trigger Property="Text" Value="3">
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                    <Trigger Property="Text" Value="4">
                        <Setter Property="Background" Value="White" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>
</DataTemplate>

Notice that the method SelectAll() of the TextBox called on GotFocus event has a little trick to work as intended. 请注意,在GotFocus事件上调用的TextBox的SelectAll()方法具有一些可以按预期工作的技巧。 Check this SO question: How to automatically select all text on focus in WPF TextBox? 请检查以下SO问题: 如何自动选择WPF TextBox中焦点上的所有文本?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM