I'm using a simple ComboBox in GXT that gets its values from the database.
What I want is that everytime that the user clicks (expands) the ComboBox, it will check and re-populate it with the latest entries in the database (in case they've changed).
Right now I'm doing something like:
ProtocolProperties protocolProperties = GWT.create(ProtocolProperties.class);
final ListStore<ProtocolDto> protocolStore = new ListStore<ProtocolDto>(protocolProperties.id());
protocol = new ComboBox<ProtocolDto>(protocolStore, protocolProperties.name());
protocol.addExpandHandler(new ExpandHandler() {
#Override
public void onExpand(ExpandEvent event) {
protocolStore.clear();
ProtocolDto emptyDto = new ProtocolDto();
emptyDto.setId(-1);
emptyDto.setName("None");
protocolStore.add(emptyDto);
AppEntryPoint.getLogbookdataservice().getAllProtocols(new AsyncCallback<List<ProtocolDto>>() {
#Override
public void onSuccess(List<ProtocolDto> result) {
protocolStore.addAll(result);
}
#Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
});
}
});
Thanks to anyone who takes the time to answer this.
You should be looking at Async Support in Combobox instead of reinventing a square wheel.
Sencha Demo - http://www.sencha.com/examples/#ExamplePlace:advancedcombobox
Stackoverflow - Also one approach discussed here - Dynamic Autosuggest Combobox in GXT
GXT Forum - http://www.sencha.com/forum/showthread.php?185967-ComboBox-doQuery-method-seems-not-working-with-Remote-Loader
Related
Specifically this is a follow-up to this question DataGrid filter performance, but there are many more similar questions relating to WPF DataGrid performance on StackOverflow.
After a lot of profiling and going through .NET source code, I have realized that many performance issues, such as filtering and sorting, boil down just one issue: A CollectionView.Reset event does not recycle containers (like scrolling does).
What I mean is that instead of assigning the existing rows a new datacontext, all rows are removed from the visual tree, new rows are generated and added, and a layout cycle (measure and arrange) is performanced.
So the main question is: Has anyone successfully managed to work around this? E.g. by manually manipulating the ItemContainerGenerator, or by creating their own version of the DataGridRowsPresenter?
So this is the gist of my approach so far.
public class CollectionViewEx
{
public event EventHandler Refresh;
public override void Refresh()
{
Refresh?.Invoke(this, EventArgs.Empty);
}
}
public class DataGridEx : DataGrid
{
protected override OnItemsSourceChanged(IEnumerable oldSource, IEnumerable newSource)
{
if (newSource is CollectionViewEx cvx)
{
cvx.Refresh += (o,a) => OnViewRefreshing;
}
}
private void OnViewRefreshing()
{
RowsPresenter.Refresh();
}
}
public class DataGridRowsPresenterEx : DataGridRowsPresenter
{
public void Refresh()
{
var generator = (IRecyclingItemContainerGenerator)ItemContainerGenerator;
generator.Recycle(new GeneratorPosition(0, 0), ???);
RemoveInternalChildRange(0, VisualChildrenCount);
using (generator.StartAt(new GeneratorPosition(-1, 0), GeneratorDirection.Forward))
{
UIElement child;
bool isNewlyRealised = false;
while ((child = generator.GenerateNext(out isNewlyRealised) as UIElement) != null)
{
AddInternalChild(child);
generator.PrepareItemContainer(child);
}
}
}
}
But the results are very confusing - obviously because I don't quite understand how to work with the ICG.
I have looked through .net source code to see their implementations (when adding/removing/replacing items), and also found a couple of online resources on how to create a new virtualized panel (e.g. virtualizingwrappanel), but none really address this particular issue, where we want to reuse all existing containers for a new set of items.
So the secondary question is: Can anyone explain if this approach is even possible? How would I do it?
I never use reset directly from CollectionView because a methode on CollectionView's Source do it. This IList is modified for my needs. I did it like Paul McClean explained here.
In this class you could notify OnCollectionChanged to inform the CollectionView. sondergard explained what NotifyCollectionChangedAction.Reset do. But NotifyCollectionChangedAction.Replace keep running the recyling for the Items.
Maybe my research helps.
i am new to wpf and i need to open up a pop up a new window on grid row click which contains lots of data and controls on it.i am confused with the correct approach. i am using mvvm pattern.should i make a window control or user control or something else. and how to open that pop up inside a function. please help with example
If I need to display a new Window in my MVVM-Application I use the following approach:
At first I have an interface with a method to show the new dialog:
internal interface IDialogManager
{
void DisplayData(object data);
}
And an implementation like:
internal class DialogManager : IDialogManager
{
public void DisplayData(object data)
{
LotOfDataViewModel lotOfDataViewModel = new LotOfDataViewModel(data);
LotOfDataView lotOfDataView = new LotOfDataView
{
DataContext = lotOfDataViewModel
};
lotOfDataView.ShowDialog();
}
}
LotOfDataViewModel and LotOfDataView are the new Dialog where you want to show your data.
In your actual ViewModel you introduce a new property like:
private IDialogManager dialogManager;
private IDialogManager DialogManager
{
get { return dialogManager ?? (dialogManager = new DialogManager()); }
}
And the you can show your large data with:
DialogManager.DisplayData(myData);
I've started writing my first WPF/MVVM and as many other people have found, dealing with navigation between views is rather confusing.
I've been searching for a while and most of the topics either recommend using MVVM Light/PRISM, or come up with solutions similar to one from here.
I'm trying to approach an MVVM navigation mechanism in which I can switch directly from one view to another view (without using the datatemplate switch from the parent window). Let's say, I have an app with a main window loading dynamic content from different usercontrols (views).
The MainWindowViewModel would have a CurrentV property pointed to, say, UserListV and a CurrentVM property pointed to UserListVM. Now that I select one user from the list and click on the View button to view that user details in another screen of the same window. This should allow me to switch to the UserV with UserVM as data context.
I wonder how should I, while being on UserListVM, make a call to MainWindowViewModel to update the CurrentV and CurrentVM values, and switching the window to the UserV accordingly?
Any suggestion of a better idea is more than welcome!
Thank you very much!
I use a messaging service for communication between ViewModels, while still keeping them decoupled. If you are using MVVMLight, it comes with one. I prefer not to use an MVVM framework, and write my own messaging service. Here is an example of one from a recent project:
public class MessageService : IMessageService
{
private List<IMessageSubscription> subscribers; //list of subscription objects registered
public MessageService()
{
subscribers = new List<IMessageSubscription>();
}
public void Subscribe<T>(string message, Action<T> action)
{
subscribers.Add(new MessageSubscription<T>()
{
Message = message,
MessageActionWithArgs = action
});
}
public void Subscribe(string message, Action action)
{
subscribers.Add(new MessageSubscription<bool>()
{
Message = message,
MessageActionNoArgs = action
});
}
public void Send<T>(string message, T args)
{
IEnumerable<IMessageSubscription> matches = subscribers.Where(x => x.Message == message && x.PayLoadType == typeof(T));
foreach (IMessageSubscription sub in matches.ToList())
{
sub.InvokeMessageAction((T)args);
}
}
public void Send(string message)
{
IEnumerable<IMessageSubscription> matches = subscribers.Where(x => x.Message == message);
foreach (IMessageSubscription sub in matches.ToList())
{
sub.InvokeMessageAction();
}
}
}
So, for example, MainViewModel would listen for a message such as "ActiveViewModelChangeRequest", and other viewmodels would send that message when they need to become active. So, in MainViewModel you would have something like this:
public MainViewModel()
{
messageService.Register<ViewModelBase>("ActiveViewModelChangeRequest", UpdateActiveViewModel);
}
private void UpdateActiveViewModel(ViewModelBase viewModel)
{
this.CurrentVM = viewModel;
}
And then in UserListVM you would have:
private void OnUserSelect(object sender, UserSelectionEventArgs e)
{
UserVM viewModel = new UserVM(SelectedUser);
messageService.Send<ViewModelBase>("ActiveViewModelChangeRequest, viewModel);
}
There's a lot of reading material available on the messenger pattern for MVVM applications. I would suggest reading up on this.
I have a strange problem here. We develop a Windows 10 Universal App and now I want to update my listview when I add new value. But unfortunately it wont work and I dont really know why. When I add new value it won't update my list view.
The data comes from a background-thread (REST-Request against Server) and therefore I know, I should use something that runs the "add-functionality" on the UI-Thread.
First of all I declared a IProgress and my collection:
private List<dtoGemeinde> _listeGemeinden = new List<dtoGemeinde>();
public List<dtoGemeinde> GemeindenCollection
{
get { return this._listeGemeinden; }
}
IProgress<dtoGemeinde> prog;
prog = new Progress<dtoGemeinde>(UpdateListViewUI);
This is the "UpdateListViewUI" method:
public void UpdateListViewUI(dtoGemeinde dto)
{
_listeGemeinden.Add(dto);
this.listViewGemeinden.ItemsSource = GemeindenCollection;
}
And this is the callback method which is called when the background thread, which loads the data from the server, is finished:
public async void onCallBackGemeinden(List<dtoGemeinde> listeGemeinden)
{
if (listeGemeinden != null && listeGemeinden.Count > 0)
{
this.progress.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
foreach (dtoGemeinde dto in listeGemeinden)
{
await listViewGemeinden.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => prog.Report(dto));
}
}
else
{
await new MessageDialog("Data cant be load", "Error").ShowAsync();
}
}
ObservableCollection instead of List usually works fine if need to bind a ListView and be able to see the updates, if this doesn't work any underlying class might need to implement the INotifyChanged pattern to update any properties within the collection if needed.
I want to use the exportWizard extension point for an eclipse plugin. I am having some difficulties figuring out how a simple filedialog wizard page should look like.
public class ExportWizardPage extends WizardPage {
private FileDialog fileDialog=null;
protected ExportWizardPage(String pageName) {
super(pageName);
}
#Override
public void createControl(Composite parent) {
fileDialog = new FileDialog(parent.getShell(), SWT.SAVE);
fileDialog.setFilterExtensions(new String[] { "*.bm" });
}
}
I am trying it currently like above and use a FileDialog for selecting the target file. Basically it works, the dialog is opened and I get the name of the file, but as soon the dialog closes I get an exception.
org.eclipse.core.runtime.AssertionFailedException: null argument:
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:85)
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:73)
at org.eclipse.jface.wizard.Wizard.createPageControls(Wizard.java:178)
I think I am using this Wizard/WizardPage mechanism wrongly, but I really could not found a simple example that showed me how something should look like.
Your wizard page does not contain any controls. You should create one composite and then add all your controls to it (and NOT parent directly). Calling setControl(..) is also absolutely required. It should look something like this:
#Override
public void createControl(Composite parent) {
Composite content = new Composite(parent, SWT.NONE);
// add all the controls to your wizard page here with 'content' as parent
FileDialog fileDialog = new FileDialog(parent.getShell(), SWT.SAVE);
fileDialog.setFilterExtensions(new String[] { "*.bm" });
setControl(content);
}