簡體   English   中英

如何在item.refresh之后專注於WPF列表視圖中文本框的鍵盤

[英]how to focus on the keyboard on a textbox in WPF listview after item.refresh

我有一個 WPF 窗口,其中有一個帶有文本框的列表視圖,我想讓用戶能夠使用 TAB 鍵在文本框之間切換。 我創建了一個執行此操作的函數,但是每次文本框失去焦點時,我都會刷新列表視圖,因此列表視圖本身會獲得焦點。

我知道問題是由於刷新事件而發生的,因為評論該部分將導致正確的元素(文本框)被聚焦。 我嘗試了許多替代解決方案,但都沒有奏效( 防止項目在 c# 中刷新列表視圖時失去焦點在 ListView 'SelectionChanged' 事件后專注於 TextBox )。

似乎在刷新列表視圖后關注該元素存在問題。

我嘗試記住項目的索引,然后在按下 TAB 鍵后專注於它。 還嘗試記住焦點控件,然后在刷新后專注於它。

    private void RTB_Reference_LostFocus(object sender, RoutedEventArgs e)
    {
        int Index = DetailsList.SelectedIndex;
        Index = DetailsList.Items.IndexOf(DetailsList.SelectedItem);

        try
        {
            //Get cell value by using sender Object
            string inTime = ((System.Windows.Controls.TextBox)sender).Text;

            DetailItem item = (DetailItem)DetailsList.Items[Index];
            item.Reference = inTime;

            UpdateExplanation(item);

        }

        catch (Exception)
        {

        }
    }

    private void RTB_Detail_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        if (e.Key == Key.Tab)
        {
            e.Handled = true;
            //System.Windows.MessageBox.Show("Tab");
            int Idx = DetailsList.SelectedIndex;
            System.Windows.Controls.ListViewItem lvi = (System.Windows.Controls.ListViewItem)DetailsList.ItemContainerGenerator.ContainerFromItem(DetailsList.SelectedItem);
            GUF.FocusItem(DetailsList, Idx, "RTB_Detail");
            //IsLastKeyTAB = true;
        }
        //else
        //    IsLastKeyTAB = false;

    }

    private void UpdateExplanation(DetailItem item)
    {

        item.Explanation = GetExplanation(item.Reference, item.Detail);

        IInputElement focusedControl = Keyboard.FocusedElement;
        DetailsList.Items.Refresh();
        focusedControl.Focus();

        RefreshDetailsList(DetailsList, IsEnglish);


    }

預期的結果是在刷新后繼續關注該文本框。 那不會發生...

編輯 1

這是列表視圖 xaml:

    <ListView FlowDirection="RightToLeft" x:Name="DetailsList" VirtualizingStackPanel.IsVirtualizing="False" 
        HorizontalAlignment="Stretch" VerticalAlignment="Top"
        HorizontalContentAlignment="Center" ScrollViewer.VerticalScrollBarVisibility="Visible" Padding="0 0 0 25"
        AllowDrop="True"
        ItemsSource="{Binding DetailItem}"
        Loaded="ListView_Loaded"
        Margin="26,157,23,0"
        dd:DragDrop.IsDragSource="True"
        dd:DragDrop.IsDropTarget="True"
        dd:DragDrop.DropHandler="{Binding}" Height="599">


        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="BorderThickness" Value="0" />
                <Setter Property="Foreground" Value="Black" />
                <Setter Property="Margin" Value="4, 4, 4, 4"/>
                <Setter Property="FontWeight" Value="DemiBold"/>
                <Setter Property="Height" Value="22"/>
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListViewItem}">
                            <Border BorderBrush="Transparent" BorderThickness="0" Background="{TemplateBinding Background}">

                                <GridViewRowPresenter HorizontalAlignment="Stretch" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Width="Auto" Margin="0" Content="{TemplateBinding Content}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>

                <Style.Triggers>

                    <Trigger Property="IsMouseOver" Value="True">
                        <!--   <Setter Property="Background" Value="#6B54FF"/> -->
                        <Setter Property="Foreground" Value="#6B57FF"/>
                        <Setter Property="BorderThickness" Value="2" />
                    </Trigger>

                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="BorderThickness" Value="2" />
                        <Setter Property="BorderBrush" Value="#6B57FF"/>
                        <Setter Property="Foreground" Value="#6B57FF" />
                    </Trigger>
                </Style.Triggers>

            </Style>
        </ListView.ItemContainerStyle>




        <ListView.View>
            <GridView>

                <GridViewColumn Width="50" Header="סימון" DisplayMemberBinding="{Binding Mark}"/>

                <!--
                                <GridViewColumn Width="30" >
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate >
                                            <Button Style="{StaticResource PlusButtonStyle}" x:Name="buttonPlusDocument" Click="buttonPlusDocument_Click"  />
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                                -->
                <GridViewColumn Header="הפניה במסמך" Width="150">
                    <GridViewColumn.CellTemplate>

                        <DataTemplate>

                            <TextBox x:Name="RTB_Reference" BorderBrush="#5f27ff" BorderThickness="1" KeyDown="RTB_Reference_KeyDown" HorizontalAlignment="Stretch" Height="20" Margin="0" Padding="0" FontSize="12" IsEnabled="True" 
                                LostFocus="RTB_Reference_LostFocus" GotFocus="RTB_Reference_GotFocus">

                                <TextBox.Resources>
                                    <Style TargetType="{x:Type Border}">
                                        <Setter Property="CornerRadius" Value="2"/>
                                        <Setter Property="BorderBrush" Value="#5f27ff"/>
                                        <Setter Property="BorderThickness" Value="1" />
                                    </Style>
                                </TextBox.Resources>
                            </TextBox>
                            <!--DataContext="{Binding SelectedItem, ElementName=ListViewAppendixNameList, Mode=TwoWay}"-->

                        </DataTemplate>

                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn Header="פרט" Width="150">
                    <GridViewColumn.CellTemplate>

                        <DataTemplate>

                            <TextBox x:Name="RTB_Detail" BorderBrush="#5f27ff" BorderThickness="1" HorizontalAlignment="Stretch" Height="20" Margin="0" Padding="0" FontSize="12" IsEnabled="True" 
                                KeyDown="RTB_Detail_KeyDown" LostFocus="RTB_Detail_LostFocus" GotFocus="RTB_Detail_GotFocus">

                                <TextBox.Resources>
                                    <Style TargetType="{x:Type Border}">
                                        <Setter Property="CornerRadius" Value="2"/>
                                        <Setter Property="BorderBrush" Value="#5f27ff"/>
                                        <Setter Property="BorderThickness" Value="1" />
                                    </Style>
                                </TextBox.Resources>
                            </TextBox>
                            <!--DataContext="{Binding SelectedItem, ElementName=ListViewAppendixNameList, Mode=TwoWay}"-->

                        </DataTemplate>

                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn Header="הסבר" Width="350"  DisplayMemberBinding="{Binding Explanation}"/>



                <GridViewColumn Width="30" >
                    <GridViewColumn.CellTemplate>

                        <DataTemplate >

                            <Button Style="{StaticResource DeleteButtonStyle}" x:Name="BT_DeleteDetail" Click="BT_DeleteDetail_Click"  />

                        </DataTemplate>

                    </GridViewColumn.CellTemplate>
                </GridViewColumn>


            </GridView>
        </ListView.View>
    </ListView>

這是詳細信息類:

    public class DetailItem
    {
        public string Mark { get; set; }
        public string Reference { get; set; }
        public string Detail { get; set; }
        public string Explanation { get; set; }
    }

我刷新列表視圖,以便更新說明文本。

我沒有瀏覽您的整個代碼,而只瀏覽了與您的問題相關的那些部分。 為簡化起見,我將使用附加屬性TabNavigation數據綁定功能。 綁定將自動更新控件值,從而使ListView的刷新和焦點處理變得多余。

備注:為了縮短 XAML 代碼,我將只顯示相關的代碼部分。

標簽導航

ListView上的附加屬性KeyboardNavigation.TabNavigation設置為Continue以便焦點將在列表中循環:

  <ListView x:Name="DetailsList"
            KeyboardNavigation.TabNavigation="Continue"
            ...
  </ListView>

您可以通過在元素上設置IsTabStop屬性來控制哪些元素可以接收按下 Tab 鍵的焦點。 默認值為True 因此,在您希望排除的元素上將其設置為False 禁用ListViewItem本身的 Tab 焦點很有用,以便 Tab 鍵僅對包含的控件有效:

    <ListView.ItemContainerStyle>
      <Style TargetType="{x:Type ListViewItem}">
        <Setter Property="IsTabStop"
                Value="False" />
        ...
      </Style>
    </ListView.ItemContainerStyle>

如果您還希望排除Button ,以便僅在TextBox元素之間跳轉,請將ButtonIsTabStop屬性也設置為False

        <GridViewColumn Width="30">
          <GridViewColumn.CellTemplate>
            <DataTemplate>
              <Button x:Name="BT_DeleteDetail"
                      IsTabStop="False" 
                      ...
              />
              ...
            </DataTemplate>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>

如果您還希望更改元素在 Tab 鍵按下時獲得焦點的順序,您可以通過設置元素的TabIndex屬性來實現。 具有較低標簽索引的控件在具有較高索引的控件之前獲得焦點。

綁定TextBox

要啟用與數據模型的綁定,需要數據模型(視圖模型)實現INotifyPropertxChanged

public class DetailItem : INotifyPropertyChanged
{
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private string mark;
  public string Mark
  {
    get => this.mark;
    set
    {
      if (value == this.mark) return;
      this.mark = value;
      OnPropertyChanged();
    }
  }

  private string reference;
  public string Reference
  {
    get => this.reference;
    set
    {
      if (value == this.reference) return;
      this.reference = value;
      OnPropertyChanged();
    }
  }

  private string detail;
  public string Detail
  {
    get => this.detail;
    set
    {
      if (value == this.detail) return;
      this.detail = value;
      OnPropertyChanged();
    }
  }

  private string explanation;
  public string Explanation
  {
    get => this.explanation;
    set
    {
      if (value == this.explanation) return;
      this.explanation = value;
      OnPropertyChanged();
    }
  }
}

為了從您的DataTemplate訪問視圖模型,請將其DataType屬性設置為視圖模型的類型 ( DetailItem )。 請記住始終設置DataTemplateDataType 然后將Binding添加到TextBox 請注意,綁定的Mode (方向)設置為OneWayToSource 這將綁定限制為僅將TextBox數據設置為DetailItem

          <GridViewColumn.CellTemplate>
            <DataTemplate DataType="viewModels:DetailItem">
              <TextBox x:Name="RTB_Reference"
                       Text="{Binding Reference, Mode=OneWayToSource}"
                       ... 
              </TextBox>
              ...
            </DataTemplate>
          </GridViewColumn.CellTemplate>

          <GridViewColumn.CellTemplate>
            <DataTemplate DataType="viewModels:DetailItem">
              <TextBox x:Name="RTB_Detail"
                       Text="{Binding Detail, Mode=OneWayToSource}"
                       ... 
              </TextBox>
              ...
            </DataTemplate>
          </GridViewColumn.CellTemplate>

最后一步是更新DetailItem.Explanation屬性。 為此,我們將UpdateExplanation()方法移動到視圖模型DetailItem 由於我們使用了綁定,我們現在可以去掉里面所有的ListView刷新和焦點邏輯,所以方法變小了。 請注意,由於我們將方法移到DetailItem類中,因此我們還可以刪除該方法的參數:

private void UpdateExplanation()
{
  this.Explanation = GetExplanation(this.Reference, this.Detail);
}

UpdateExplanation()方法直接從ReferenceDetail屬性的 setter 調用,因此每次更改這些屬性時,都會更新Explanation值。 使用更新的ReferenceDetail setter, DetailItem類的最終版本將如下所示:

public class DetailItem : INotifyPropertyChanged
{
    private void UpdateExplanation()
    {
      this.Explanation = GetExplanation(this.Reference, this.Detail);
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private string mark;
    public string Mark
    {
      get => this.mark;
      set
      {
        if (value == this.mark) return;
        this.mark = value;
        OnPropertyChanged();
      }
    }

    private string reference;
    public string Reference
    {
      get => this.reference;
      set
      {
        if (value == this.reference) return;
        this.reference = value;
        OnPropertyChanged();
        UpdateExplanation();
      }
    }

    private string detail;
    public string Detail
    {
      get => this.detail;
      set
      {
        if (value == this.detail) return;
        this.detail = value;
        OnPropertyChanged();
        UpdateExplanation();
      }
    }

    private string explanation;
    public string Explanation
    {
      get => this.explanation;
      set
      {
        if (value == this.explanation) return;
        this.explanation = value;
        OnPropertyChanged();
      }
    }
  }

試試下面的代碼。 享受 !!!

<Grid>
    <ListView Margin="45.5,47.5,41.167,0" Name="lvtestListview"   Height="188.333" VerticalAlignment="Top">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                <Setter Property="VerticalContentAlignment"  Value="Stretch"/>
                <!--<Setter Property="IsSelected" Value="{Binding IsGroovy}"/>-->

                <Style.Triggers>
                    <Trigger Property="IsSelected" Value="true" >
                        <Setter Property="Foreground" Value="Blue" />
                        <Setter Property="Background" Value="LightGreen" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Item Code" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Border BorderBrush="Gray"  BorderThickness=".5" Margin="-6,-3">
                                <TextBlock Text="{Binding ItemCode}"  Margin="6,3"/>
                            </Border>

                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>             
                <GridViewColumn Header="Item Name" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Border BorderBrush="Gray" BorderThickness=".5" Margin="-6,-3">
                                <TextBox Loaded="txtBarcode_Loaded"  Text="{Binding ItemName}" Name="txtBarcode" Focusable="{Binding IsFocused}"      Cursor="IBeam" />
                            </Border>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>             
                <GridViewColumn Header="Next Item" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Border BorderBrush="Gray" BorderThickness=".5" Margin="-6,-3">
                                <TextBox TabIndex="3" Name="txtgvPL1" KeyDown="txtgvPL1_KeyDown" Text="{Binding PL1}"  Cursor="IBeam"/>

                            </Border>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

</Grid>

背后的代碼

公共類 ClassA:INotifyPropertyChanged {

    public string ItemCode { get; set; }
    public string ItemName { get; set; }
    

    private bool isFocused;


    public event PropertyChangedEventHandler PropertyChanged;



  


    public bool IsFocused
    {

        get
        {
            return isFocused;
        }

        set
        {
            if (value != isFocused)
            {
                isFocused = value;
                RaisePropertyChanged("IsFocused");

            }
        }


    }



    private void RaisePropertyChanged(string propName)
    {
      

        PropertyChangedEventHandler eh = PropertyChanged;
        if (eh != null)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }



}




public partial class MainWindow : Window
{

    List<ClassA> lstClassA = new List<ClassA>();
    public MainWindow()
    {
        InitializeComponent();
        BindGrid();
    }

    private void BindGrid()
    {
       

        ClassA ca = new ClassA();
        ca.ItemCode = "A";
       
        ca.IsFocused = true;

        lstClassA.Add(ca);


        lvtestListview.ItemsSource = lstClassA;


     }

    private void txtBarcode_Loaded(object sender, RoutedEventArgs e)
    {
        Keyboard.Focus(((TextBox)sender));
    }

    private void txtgvPL1_KeyDown(object sender, KeyEventArgs e)
    {

        if (e.Key == Key.Enter  )
        {
            ClassA ca = new ClassA();
            ca.ItemCode = "B";
            ca.IsFocused = true;

            lstClassA.Add(ca);


            foreach (ClassA a in lstClassA)
            {
                if (a.ItemCode == "A")
                {
                    a.IsFocused = false;
                }

            }


            lvtestListview.ItemsSource = lstClassA;
            lvtestListview.Items.Refresh(); 

        }

      

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM