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