WPF Autocompletebox MVVM如何从另一个控件获取selectedItem? [英] WPF Autocompletebox MVVM how to get selectedItem from another control?

查看:84
本文介绍了WPF Autocompletebox MVVM如何从另一个控件获取selectedItem?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试开发一个WPF用户控件(下图),该控件使我可以按姓名或编号搜索客户.为此,我使用了MVVM方法(MVVM Light).

I try to develop a WPF user control (image below) that allows me to search customer by name or Number. To achieve this, I use MVVM Approach (MVVM Light).

我如何同时实现以下目标:

How can i achieve the following goals at the same time :

1°)如果我知道数字,可以在文本框中输入该名称,该名称将自动出现在AutoCompleteBox中.

1°) If I know the number I can enter it in the textbox and the name will automatically appear in the AutoCompleteBox

2°)如果客户编号未知,我将使用自动完成框按名称搜索,则文本框必须包含所选客户的编号.

2°) If the customer number is unknown ,i use autocompletebox to search by name, then the Textbox must contain the number of selected customer .

问题是: 如果我将文本框绑定到Autocompletebox selectedItem,则实现了第二个目标,但没有达到第一个目标.当我在文本框中按Enter键时,即使其中包含有效的代码,我也总是显示找不到客户"的消息.并且客户代码为空,就像未绑定到AutocompleteBox SelectedItem一样.

The problem is : If i bind the textbox to the Autocompletebox selectedItem, second goal is achieved but not the first. When i press Enter key in the textbox, even when it contains valid code, I have always message "Customer not found." and the customer code is empty as if it is not bound to AutocompleteBox SelectedItem.

下面的代码:

//snipped from user control
 <TextBox Text="{Binding ElementName=custName, Path=SelectedItem.CodeClient, UpdateSourceTrigger=PropertyChanged}" Width="80"  Margin="8,8,0,8">

                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="PreviewKeyDown">
                        <gs:EventToCommand PassEventArgsToCommand="True"
                                Command="{Binding GetClientCommand, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
            <Button Content="..." Margin="0,8,2,8" Width="20" Command="{Binding SearchCommand}"/>
            <Label Content="Name" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,5,0,5"/>
            <controls:AutoCompleteBox x:Name="custName"  
                                        ItemsSource="{Binding ListClients}" 
                                        MinimumPrefixLength="3"
                                        MinimumPopulateDelay="200"
                                        ValueMemberBinding="{Binding Path=NomClient, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
                                        Text="{Binding Path=ClientName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                                        SelectedItem="{Binding ElementName=this, Path=CodeClient,  Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
                                        FilterMode="Contains"
                                        IsTextCompletionEnabled="True"
                                        Width="400" 
                                        Margin="2,8,5,8" 
                                      >
                <controls:AutoCompleteBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="Auto">
                        <TextBlock Text="{Binding Path=CodeClient, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="5" />
                        <TextBlock Text="{Binding Path=NomClient, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"  Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </controls:AutoCompleteBox.ItemTemplate>
            </controls:AutoCompleteBox>
        </StackPanel>



 //light class for customer contains only code and name for use in autocompletebox

  public class ClientReduit : ObservableObject
{
    string _codeclient;

    public string CodeClient
    {
        get { return _codeclient; }
        set { _codeclient = value;
        RaisePropertyChanged("CodeClient");
        }
    }

    string _nomclient;

    public string NomClient
    {
        get { return _nomclient; }
        set { _nomclient = value;
        RaisePropertyChanged("NomClient");
        }
    }

    long? _clientid;

    public long? Clientid
    {
        get { return _clientid; }
        set { _clientid = value; 
        }
    }

}


//-------ViewModel de UserControl CustomerSearch
public class ViewModelRechercheClient : ObservableObject
{


    Client _client;
    string _codeClient;
    string _nomClient;
    bool   _clientFound = false;

    public bool ClientFound
    {
        get { return _clientFound; }
        set { _clientFound = value;}
    }


    ObservableCollection<ClientReduit> _listClients;

    public ObservableCollection<ClientReduit> ListClients
    {
        get
        {
            if (_listClients == null)
                _listClients = new ObservableCollection<ClientReduit>();
            return _listClients;
        }

        set
        {
            _listClients = value;
            RaisePropertyChanged("ListClients");
        }

    }

    public Client CurrentClient
    {
        get { return _client; }
        set { _client = value; }
    }


    public string ClientName
    {
        get { return _nomClient; }
        set { _nomClient = value;
        RaisePropertyChanged("ClientName");
        }
    }


    public string ClientCode
    {
        get { return _codeClient; }
        set { _codeClient = value;
        RaisePropertyChanged("ClientCode");
        }
    }


//Constructor
 public ViewModelRechercheClient()
    {

     //Load customers
 ListClients = new ObservableCollection<ClientReduit>((from c in (((App)Application.Current).GetListClient())
                      select new ClientReduit
                                    {
                                        CodeClient = c.r01_codcli,
                                        NomClient = c.r01_nomcli.Trim(),
                                        Clientid = c.CLIENTID

                                    }).ToList());


    }


    //Command for TextBox PreviewkeyDown -> Key.Enter --> 
    ICommand _getClient; 

    //---------------------------------------------------------------------------------
    //Commande de recherche client lors de l'entrée d'un code client et de l'appui sur 
    //la touche entrée
    //---------------------------------------------------------------------------------
    public ICommand GetClientCommand
    {
        get
        {
            if (_getClient == null)
                _getClient = new RelayCommand<KeyEventArgs>(GetClientCommandExecute);
            return _getClient;
        }
    }


    private void GetClientCommandExecute(KeyEventArgs e)
    {
        bool processIt = false;
        ClientFound = false;
        if (e != null && e.Key == Key.Enter)
            processIt = true;
        if (e == null || processIt == true)
        {

            ILogger _currentLog = ((App)Application.Current).GetCurrentLogger();
            using (UnitOfWork cx = new UnitOfWork(_currentLog))
            {
                ClientRepository _clientRepository = new ClientRepository(cx, _currentLog);
                IClientManagementService cms = new ClientManagementService(_currentLog, _clientRepository);

                CurrentClient = cms.FindById(ClientCode);

                if (CurrentClient != null)
                {
                    ClientFound = true;
                    ClientCode = CurrentClient.r01_codcli;
                    ClientName = CurrentClient.r01_nomcli;

                }
                else
                {
                    ClientFound = false;
                    Messenger.Default.Send(new APPX.Presentation.Messages.DialogMessage(ClientCode + " : Customer not found."));
                }

            }
        }
    }

我认为问题在于如何在尊重MVVM方法的同时从AutoCompleteBox SelectedItem获取客户编号?

I think the Question lies in how to get the Customer Number from AutoCompleteBox SelectedItem while respecting MVVM Approach ?

先谢谢您

推荐答案

我找到了一个解决方案,但我不知道它是否是最好的,但是对我来说效果很好: 简单地说,我添加了一个处理SelectionChanged事件的命令.在此命令中,我获得了selectedItem并将其分配给ClientCode(绑定到textBox)

I found a solution, but I do not know if it is the best, but it works well for me : Simply, i add a command that handle SelectionChanged event. in this command i get selectedItem and i assign it to ClientCode (bound to textBox)

在用户控件的代码下方

<StackPanel Orientation="Horizontal">
            <Label Content="Number" Grid.Column="0"  HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,5,0,5" />


           <!-- <TextBox Text="{Binding ElementName=custName, Path=SelectedItem.CodeClient, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
                     Width="80"  
                     Margin="8,8,0,8">-->
                <TextBox  x:Name="custCode" Text="{Binding ClientCode, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="8,8,0,8" Width="80">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="PreviewKeyDown">
                        <gs:EventToCommand PassEventArgsToCommand="True"
                                Command="{Binding GetClientCommand, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
            <Button Content="..." Margin="0,8,2,8" Width="20" Command="{Binding SearchCommand}"/>
            <Label Content="Name" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,5,0,5"/>
            <controls:AutoCompleteBox x:Name="custName"  
                                        ItemsSource="{Binding ListClients}" 
                                        MinimumPrefixLength="3"
                                        MinimumPopulateDelay="200"
                                        ValueMemberBinding="{Binding Path=NomClient, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
                                        Text="{Binding Path=ClientName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                                        SelectedItem="{Binding ElementName=this, Path=CodeClient,  Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
                                        FilterMode="Contains"
                                        IsTextCompletionEnabled="True"
                                        Width="400" 
                                        Margin="2,8,5,8" 
                                      SelectionChanged="custName_SelectionChanged"
                                      >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <gs:EventToCommand PassEventArgsToCommand="True"
                                Command="{Binding SetCodeClientCommand, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
                <controls:AutoCompleteBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Width="Auto">
                        <TextBlock Text="{Binding Path=CodeClient, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"  Margin="5" />
                        <TextBlock Text="{Binding Path=NomClient,  UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"  Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </controls:AutoCompleteBox.ItemTemplate>
            </controls:AutoCompleteBox>
        </StackPanel>

,命令如下:

public ICommand SetCodeClientCommand
    {
        get
        {
            if (_setCodeClient == null)
                _setCodeClient = new RelayCommand<SelectionChangedEventArgs>(SetCodeClientCommandExecute);
            return _setCodeClient;
        }
    }


    private void SetCodeClientCommandExecute(SelectionChangedEventArgs e)
    {

        if (e.AddedItems.Count > 0)
        {
            ClientCode = (((ClientReduit)e.AddedItems[0]).CodeClient);
            ClientFound = true;
        }

    }

这篇关于WPF Autocompletebox MVVM如何从另一个控件获取selectedItem?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆