2016-07-25 12 views
-2

私は単純なオートコンプリートTextBoxを作成していて、値のリストを持っています。ユーザーが文字列を入力すると、適切な文字列が表示されます。TextChangedのメソッドを呼び出すがすべてではない

今、私は私のViewModelに結合する性質を持つ私のテキストボックスを作成しました:

<TextBox Text="{Binding ServerURL, UpdateSourceTrigger=PropertyChanged}" /> 

ユーザーが新しい文字を入力したときので、それは解雇する私の財産をトリガーするため、取得するメソッドを起動します関連する値。

private string _serverURL; 

public string ServerURL { 
    get { return _serverURL; } 
    set 
    { 
     _serverURL = value; 
     ServerURL_TextChanged(); 
     OnPropertyChanged("ServerURL"); 

    } 
} 

この方法では、文字列が参照する結果がリストボックスに表示されます。

ListBoxから値を選択すると、文字列値をTextBoxテキストプロパティに設定しますが、これを行うと、ServerURL_TextChanged()メソッドがトリガーされます。

ServerURLプロパティを設定する方法はありますか?内部でメソッドを起動する方法はありますか?

+2

ですか? –

+0

すべてのキーストロークで処理を行わないようにするには、TextChangedイベントハンドラ 'Timer timer = new Timer(200)'にタイマーを入れるだけです。それをクラス全体のタイマーにし、イベントハンドラでは、単にTime.Stop()を実行します。 Timer.Start(); 'を呼び出し、' Timer.Tick'イベントハンドラで処理します。 – Meloviz

+0

遅延プロパティを使用してプロパティの変更と設定の間の時間遅延を設定することを考えましたか? https://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.delay(v=vs.110).aspx – Will

答えて

2

解決策として、ServerURLプロパティを設定する方法を分離する必要があります。リストが変更された場合

public string ServerURL { 
    get { return _serverURL; } 
    set 
    { 
     setServerURL(value, isSetByUser = true);   
    } 
} 

private function void setServerURL(string value, bool isSetByUser){ 
     _serverURL = value; 
     ServerURL_TextChanged(isSetByUser); 
     OnPropertyChanged("ServerURL"); 
} 

あなたは、コードsetServerURL(someValue, isSetByUser = false); から呼び出し、ServerURL_TextChanged実装でそれをどうするかを決めることができます。

+0

メソッド 'setServerURL'で' _serverURL = value'をどうすればいいですか? –

+0

@BenClarkeにアクセスできない場合は、更新された答え – Artru

-1

この機能を実装する最も簡単な方法は、コードビハインドからTextChangedイベントを処理することです。ここでは、この種の意思決定のためのUIを完全に制御します。コードビハインドからUI操作を管理するためのMVVM原則に違反していません。

このようなコードビハインドの実装の例を次に示します。それが役に立つかもしれません。ただ、既存の自動完全な実装を使用しないのはなぜ

public partial class AutoCompleteComboBox : UserControl 
    { 
     private Window w; 
     public AutoCompleteComboBox() 
     { 
      InitializeComponent(); 
     } 
     ~AutoCompleteComboBox() 
     { 
      if(w == null) 
      { 
       return; 
      } 
      else 
      { 
       w.MouseLeftButtonDown -= Window_MouseLeftDown; 
      } 

     } 


     #region Behaviours 
     public void FocusTextBox() 
     { 
      txt.Focus(); 
      txt.CaretIndex = txt.Text.Length; 
     } 
     #endregion 

     #region DependencyProperties 
     public static readonly DependencyProperty InputPaddingProperty = 
      DependencyProperty.Register(
       "InputPadding", 
       typeof(Thickness), 
       typeof(AutoCompleteComboBox) 
       ); 
     public Thickness InputPadding 
     { 
      get 
      { 
       return (Thickness)GetValue(InputPaddingProperty); 
      } 
      set 
      { 
       SetValue(InputPaddingProperty, value); 
      } 
     } 
     public static readonly DependencyProperty TextBoxHeightProperty = 
      DependencyProperty.Register(
       "TextBoxHeight", 
       typeof(double), 
       typeof(AutoCompleteComboBox) 
       ); 
     public double TextBoxHeight 
     { 
      get 
      { 
       return (double)GetValue(TextBoxHeightProperty); 
      } 
      set 
      { 
       SetValue(TextBoxHeightProperty, value); 
      } 
     } 
     public static readonly DependencyProperty ItemPanelMaxHeightProperty = 
      DependencyProperty.Register(
       "ItemPanelMaxHeight", 
       typeof(double), 
       typeof(AutoCompleteComboBox) 
       ); 
     public double ItemPanelMaxHeight 
     { 
      get 
      { 
       return (double)GetValue(ItemPanelMaxHeightProperty); 
      } 
      set 
      { 
       SetValue(ItemPanelMaxHeightProperty, value); 
      } 
     } 
     public static readonly DependencyProperty ItemsSourceProperty = 
      DependencyProperty.Register(
       "ItemsSource", 
       typeof(IEnumerable), 
       typeof(AutoCompleteComboBox) 
       ); 
     public IEnumerable ItemsSource 
     { 
      get 
      { 
       return (IEnumerable)ItemsSource; 
      } 
      set 
      { 
       SetValue(ItemsSourceProperty, value); 
      } 
     } 
     public static readonly DependencyProperty DisplayMemberPathProperty = 
      DependencyProperty.Register(
       "DisplayMemberPath", 
       typeof(string), 
       typeof(AutoCompleteComboBox) 
       ); 
     public string DisplayMemberPath 
     { 
      get 
      { 
       return GetValue(DisplayMemberPathProperty).ToString(); 
      } 
      set 
      { 
       SetValue(DisplayMemberPathProperty, value); 
      } 
     } 
     public static readonly DependencyProperty TextProperty = 
      DependencyProperty.Register(
       "Text", 
       typeof(string), 
       typeof(AutoCompleteComboBox), 
       new FrameworkPropertyMetadata(
        "", 
        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault 
        ) 
       ); 
     public string Text 
     { 
      get 
      { 
       return GetValue(TextProperty).ToString(); 
      } 
      set 
      { 
       SetValue(TextProperty, value); 
      } 
     } 
     public string TargetValue { get; set; } = ""; 
     public static readonly DependencyProperty IsDropDownOpenProperty = 
      DependencyProperty.Register(
       "IsDropDownOpen", 
       typeof(bool), 
       typeof(AutoCompleteComboBox), 
       new FrameworkPropertyMetadata(
        false, 
        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault 
        ) 
       ); 
     public bool IsDropDownOpen 
     { 
      get 
      { 
       return (bool)GetValue(IsDropDownOpenProperty); 
      } 
      set 
      { 
       SetValue(IsDropDownOpenProperty, value); 
      } 
     } 
     #endregion 

     #region Events 
     private void me_Loaded(object sender, RoutedEventArgs e) 
     { 
      w = VisualTreeHelpers.FindAncestor<Window>(this); 
      w.MouseLeftButtonDown += Window_MouseLeftDown; 
      FocusTextBox(); 
     } 
     private void Window_MouseLeftDown(object sender, MouseButtonEventArgs e) 
     { 
      IsDropDownOpen = false; 
     } 
     private void lst_KeyDown(object sender, KeyEventArgs e) 
     { 
     } 
     private void lst_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      if (TargetValue != null && TargetValue.Trim().Length > 0) 
      { 
       txt.Text = TargetValue; 
       IsDropDownOpen = false; 
      } 
      FocusTextBox(); 
     } 
     private void lst_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
     } 
     private void lst_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      if (lst.SelectedItem != null) 
      { 
       TargetValue = lst.SelectedItem.ToString(); 
      } 
     } 
     private void txt_LostFocus(object sender, RoutedEventArgs e) 
     { 
      if (lst.IsFocused == false) 
      { 
       IsDropDownOpen = false; 
       FocusTextBox(); 
      } 
     } 
     private void lst_LostFocus(object sender, RoutedEventArgs e) 
     { 
      MessageBox.Show("text changed"); 
      if (txt.IsFocused == false) 
      { 
       IsDropDownOpen = false; 
      } 
     } 
     private void txt_TextChanged(object sender, TextChangedEventArgs e) 
     { 
      IsDropDownOpen = true; 
     } 
     private void txt_PreviewKeyDown(object sender, KeyEventArgs e) 
     { 
      if (IsDropDownOpen && lst.Items.Count > 0) 
      { 
       if (lst.SelectedIndex < 0) 
       { 
        lst.SelectedIndex = 0; 
       } 
       if (e.Key == Key.Up && lst.SelectedIndex > 0) 
       { 
        lst.SelectedIndex--; 
       } 
       else if (e.Key == Key.Down && lst.SelectedIndex < lst.Items.Count - 1) 
       { 
        lst.SelectedIndex++; 
       } 
       else if(e.Key == Key.Enter || e.Key == Key.Tab) 
       { 
        if(lst.SelectedIndex > -1) 
        { 
         txt.Text = TargetValue; 
         IsDropDownOpen = false; 
         FocusTextBox(); 
        } 
       } 

      } 
     } 

     #endregion 
    } 

そして、ここではXAML

<UserControl x:Class="SHARED_COMPONENTS.AutoCompleteComboBox" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      x:Name="me" 
      Loaded="me_Loaded" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <Grid> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="auto"/> 
       <RowDefinition /> 
      </Grid.RowDefinitions> 

      <TextBox 
       x:Name="txt" 
       Background="CornflowerBlue" 
       Foreground="White" 
       Grid.Row="0" 
       Text="{Binding ElementName=me, Path=Text,UpdateSourceTrigger=PropertyChanged}" 
       TextChanged="txt_TextChanged" PreviewKeyDown="txt_PreviewKeyDown" 
       Height="{Binding ElementName=me, Path=ActualHeight}" 
       Padding="{Binding ElementName=me,Path=InputPadding}" 
       /> 
      <Popup IsOpen="{Binding ElementName=me, Path=IsDropDownOpen}" ClipToBounds="False"> 
       <Border Grid.Row="1"> 
        <Border.Effect> 
         <DropShadowEffect Color="Black" /> 
        </Border.Effect> 
        <ListBox 
          x:Name="lst" 
          Grid.Row="1" 
          ItemsSource="{Binding ElementName=me, Path=ItemsSource}" 
          PreviewKeyDown="lst_KeyDown" 
          SelectionChanged="lst_SelectionChanged" 
          PreviewMouseLeftButtonDown="lst_MouseLeftButtonDown" 
          PreviewMouseLeftButtonUp="lst_PreviewMouseLeftButtonUp" 
          DisplayMemberPath="{Binding ElementName=me, Path=DisplayMemberPath }" 
          ClipToBounds="False" 
         > 
         <ListBox.Style> 
          <Style TargetType="ListBox"> 
           <Setter Property="Background" Value="#f0f0f0" /> 
           <Setter Property="Visibility" Value="Collapsed" /> 
           <Style.Triggers> 
            <MultiDataTrigger> 
             <MultiDataTrigger.Conditions> 
              <Condition Binding="{Binding ElementName=lst, Path=HasItems}" Value="True" /> 
              <Condition Binding="{Binding ElementName=me, Path=IsDropDownOpen}" Value="True" /> 
             </MultiDataTrigger.Conditions> 
             <Setter Property="Visibility" Value="Visible" /> 
            </MultiDataTrigger> 
            <DataTrigger Binding="{Binding ElementName=me, Path=IsDropDownOpen}" Value="False"> 
             <Setter Property="Visibility" Value="Collapsed" /> 
            </DataTrigger> 
           </Style.Triggers> 
          </Style> 
         </ListBox.Style> 
         <ListBox.Resources> 
          <Style TargetType="ListBoxItem"> 
           <Style.Triggers> 
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True"> 
             <Setter Property="IsSelected" Value="True" /> 
            </DataTrigger> 
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsSelected}" Value="True"> 
             <Setter Property="Foreground" Value="CornflowerBlue" /> 
            </DataTrigger> 
           </Style.Triggers> 
          </Style> 
         </ListBox.Resources> 
        </ListBox> 
       </Border> 
      </Popup> 
     </Grid> 
    </Grid> 
</UserControl> 
+0

を確認してください。私はこれをWPFアプリケーションのために特別に設計したことに言及する価値があります。しかし、あなたが探している機能をどのように実現できるかを実証するのに理想的です。 – Jace

関連する問題