WPF自动完成框MVVM如何从另一个控件获取selectedItem?

WPF自动完成框MVVM如何从另一个控件获取selectedItem?,wpf,autocomplete,mvvm-light,Wpf,Autocomplete,Mvvm Light,我尝试开发一个WPF用户控件(下图),允许我按姓名或号码搜索客户。为了实现这一点,我使用MVVM方法(mvvmlight) 我如何同时实现以下目标: 1°)如果我知道数字,我可以在文本框中输入,名称将自动显示在自动完成框中 2°)如果客户编号未知,我使用自动完成框按名称搜索,则文本框必须包含所选客户的编号 问题是: 如果我将文本框绑定到Autocompletebox selectedItem,则实现了第二个目标,但不是第一个目标。当我在文本框中按Enter键时,即使它包含有效代码,我也始终会显

我尝试开发一个WPF用户控件(下图),允许我按姓名或号码搜索客户。为了实现这一点,我使用MVVM方法(mvvmlight)

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

1°)如果我知道数字,我可以在文本框中输入,名称将自动显示在自动完成框中

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

问题是: 如果我将文本框绑定到Autocompletebox selectedItem,则实现了第二个目标,但不是第一个目标。当我在文本框中按Enter键时,即使它包含有效代码,我也始终会显示消息“Customer not found.”并且客户代码为空,就好像它没有绑定到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."));
                }

            }
        }
    }
//从用户控件剪下
//customer的light类只包含在autocompletebox中使用的代码和名称
公共类ClientReduit:observeObject
{
字符串_codeclient;
公共字符串编解码器客户端
{
获取{return\u codeclient;}
设置{u codeclient=value;
RaisePropertyChanged(“CodeClient”);
}
}
字符串\u nomclient;
公共字符串客户端
{
获取{return\u nomclient;}
设置{u nomclient=value;
RaisePropertyChanged(“NomClient”);
}
}
长?\u客户;
公共长期客户ID
{
获取{return\u clientid;}
设置{u clientid=value;
}
}
}
//-------ViewModel de UserControl CustomerSearch
公共类ViewModelRechercheClient:ObserveObject
{
客户(u客户),;
字符串_codeClient;
字符串\u nomClient;
bool\u clientFound=false;
找到公共布尔客户机
{
获取{return\u clientFound;}
集合{u clientFound=value;}
}
ObservableCollection\u ListClient;
公共可观察收集列表客户端
{
得到
{
if(_listClients==null)
_listClients=新的ObservableCollection();
返回(u)列表客户;;
}
设置
{
_ListClient=价值;
RaisePropertyChanged(“ListClient”);
}
}
公共客户端当前客户端
{
获取{return\u client;}
设置{u client=value;}
}
公共字符串ClientName
{
获取{return\u nomClient;}
设置{u nomClient=value;
RaisePropertyChanged(“客户名称”);
}
}
公共字符串客户端代码
{
获取{return\u codeClient;}
设置{u codeClient=value;
RaisePropertyChanged(“客户代码”);
}
}
//建造师
公共ViewModelRechercheClient()
{
//装载客户
ListClients=newobserveCollection((App)Application.Current.GetListClient()中的c)
选择新的ClientReduit
{
CodeClient=c.r01\u codcli,
NomClient=c.r01_nomcli.Trim(),
Clientid=c.Clientid
}).ToList());
}
//文本框预览键->键的命令。输入-->
ICommand_getClient;
//---------------------------------------------------------------------------------
//客户登记命令-客户登记代码和附件
//拉图什入口酒店
//---------------------------------------------------------------------------------
公共ICommand GetClientCommand
{
得到
{
如果(_getClient==null)
_getClient=新的RelayCommand(GetClientCommandExecute);
返回_getClient;
}
}
私有void GetClientCommandExecute(KeyEventArgs e)
{
bool processIt=false;
ClientFound=false;
如果(e!=null&&e.Key==Key.Enter)
processIt=true;
if(e==null | | processIt==true)
{
ILogger_currentLog=((App)Application.Current).GetCurrentLogger();
使用(UnitOfWork cx=新的UnitOfWork(_currentLog))
{
ClientRepository\u ClientRepository=新ClientRepository(cx,\u currentLog);
IClientManagementService cms=新的客户端管理服务(_currentLog,_clientRepository);
CurrentClient=cms.FindById(ClientCode);
如果(CurrentClient!=null)
{
ClientFound=true;
ClientCode=CurrentClient.r01\u codcli;
ClientName=CurrentClient.r01_nomcli;
}
其他的
{
ClientFound=false;
Messenger.Default.Send(新建APPX.Presentation.Messages.DialogMessage(ClientCode+“:找不到客户”);
}
}
}
}
我认为问题在于如何在尊重MVVM方法的同时从AutoCompleteBox SelectedItem获取客户编号


提前谢谢。

我找到了一个解决方案,但我不知道它是否是最好的,但它对我很有效: 简单地说,我添加了一个处理SelectionChanged事件的命令

下面是usercontrol的代码

<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;
        }

    }