ObservableCollection<someentity> not refreshing - silverlight-4.0

I am using Silverlight 4 and MVVM pattern for my application. I have a listbox that is bound to one page say one.xaml and it's viewmodel is oneviewmodel.cs. This is the page where i load my albums collection. I have a button on that page which popups a page to add a new album. Say that page is two.xaml and it's viewmodel is twoViewModel.cs. On this page i call ria services :-
context.albums.add(somealbum);
and submit the changes.The album gets added and i can see the record in sql server. However when the popup gets closed my listbox still shows the stale data. Do i need to again make a request to server to load the fresh entity just added? Thus, essentially i have to use messaging pattern and request oneviewmodel.cs to load the entities again. Is this correct way of doing?
This is my method of loading album entities :-
var qry = AlbumContext.GetAlbumsQuery(_profile.UserId);
AlbumContext.Load<Album>(qry, new Action<System.ServiceModel.DomainServices.Client.LoadOperation<Album>>(albums => {
if (GetAlbumsComplete != null)
{
if (albums.Error == null)
{
GetAlbumsComplete(this, new EntityResultArgs<Album>(albums.Entities));
}
else
{
GetAlbumsComplete(this,new EntityResultArgs<Album>(albums.Error));
}
}
}), null);
This is using the same pattern and classes as Shawn Wildermuth.
Thanks in advance :)

You do not need to load everything from the server again, but you need to add the new album to your ObservableCollection. So far you only added it to the DomainContext.
You could do one of the following two options:
1) Add the new album directly to the collection with
collection.Add(somealbum);
or
2) I assume that you fill the ObservableCollection in GetAlbumsComplete(). Just execute that part again, so that the ObservableCollection is filled with the content of your DomainContext.Albums.

Related

Revive/activate existing panels

My extension have sidebar webview that can create additional webviews as panels in the active text editor. Each of these additional webviews is for an unique item and I want to revive/activate existing webview, for the specific item, if it exists.
My issues:
I can get a list of the existing tabs with window.tabGroups.all and loop through the result. But there is no way, as far as i can see, to reactivate the desired tab. I can get some properties from there but no methods. The question here is: is there a API to get a list of the tabs and be able to revive/activate it?
Because of the first point ive decided to keep list of the instances of the additional webviews and when new webview is about the be created im checking if its unique id (in the title) is in the list and if it is then just revive the tab instead of creating a new one. Dont like this approach much but its working. The problem here is when the additional webview is closed. When closed it has to be removed from the array. Ive implemented onDidDispose for the panel but somehow the filter function, inside it, is not called:
// panels: vscode.WebviewPanel[]
// create new panel
const panel = vscode.window.createWebviewPanel(...)
// add the webview instance to the panel
const newWebview = new AdditionalWebview(panel, this.context);
this.panels.push(panel);
panel.onDidDispose(() => {
console.log("Before remove the panel"); // can see this in the console
this.panels = this.panels.filter((p) => p.title != panel.title);
console.log("Before remove the panel"); // for some reason this never appears
});
Not sure why but the panel filter functionality is never triggered (and everything after it is also not ran).
extra question: at the moment the uniqueness of the additional panels is based on their label/title. In my case thats is ok but is there any other way to get unique identifier of each tab? id/guid somewhere?
On your first question about activating a given editor, you have a couple of options.
If you know the editor's index/position in its group. That can be obtained from its tabGroup.tabs position - it seems that the tab's index in that array is faithfully its index in the editor. So you could do a Array.findIndex to get the tab uri you want to set to active.
await vscode.commands.executeCommand('workbench.action.openEditorAtIndex', [indexToOpen]);
// note the [] around the index argument
The only problem with this approach is that it works within the active group only, so you may have to activate the correct group first via:
await vscode.commands.executeCommand('workbench.action.focusSecondEditorGroup');
// or whichever group the tab you want to open is in
Or second method:
// assumes you have the tab
const openOptions = { preserveFocus: true, preview: tab.isPreview, viewColumn: tab.group.viewColumn};
// check if a uri, might be viewtype, etc., instead
if (tab.input instanceof vscode.TabInputText) {
await vscode.commands.executeCommand('vscode.open', tab.input.uri, openOptions);
}
// are your editors regular text editors?
This looks like it is opening a new tab but it will focus an existing tab if one exists at that location with that same uri.

Yii2 Gridview get all selected row for all pagination

I wrapped my gridview with Pjax widget like this
\yii\widgets\Pjax::begin();
gridview
\yii\widgets\Pjax::end();
in order to make the gridview make ajax request when I click on each pagination.
I also use ['class' => 'yii\grid\CheckboxColumn'], in column as well.
and I find that when I'm on first pagination I checked some rows and then go to second page and check some rows but when I go back to first page what I've checked is gone.
My question is how can I keep all checkedrow for all pagination
With current conditions (Pjax, multiple pages, yii\grid\CheckboxColumn) it's impossible because of the way it works.
When you click on the pagination links all GridView html content is replaced by new one that comes from the AJAX response.
So obviously all selected checkboxes on the previous page are gone.
Few possible ways to solve that:
1) Write custom javascript and server side logic.
As one of the options, you can send AJAX request to server with parameter meaning that user has chosen to select all data for the bulk delete operation (or use separate controller action for bulk deletion). In this case actually we don't need to get the selected data from user, because we can simply get them from database (credits - Seng).
2) Increase number of displayed rows per page.
3) Use infinite scroll extension, for example this.
4) Break desired action in several iterations:
select needed rows on first page, do action (for example, delete).
repeat this again for other pages.
You can get selected rows like that:
$('#your-grid-view').yiiGridView('getSelectedRows');
[infinite scroll] : http://kop.github.io/yii2-scroll-pager/ will work good if you do not have any pjax filters. If you have filters also in play, do not use this plugin as it does not support pjax filters with it. For rest of the applications it is perfect to use.
Update1 : it seems to be straight forward than expected, here is the how I accomplished it
Add following lines to the checkbox column
'checkboxOptions' => function($data){
return ['id' => $data->id, 'onClick' => 'selectedRow(this)'];
}
Now add following JS to the common js file you will have in your project of the page where this datagrid resides
var selectedItems=[]; //global variable
/**
* Store the value of the selected row or delete it if it is unselected
*
* #param {checkbox} ele
*/
function selectedRow(ele){
if($(ele).is(':checked')) {
//push the element
if(!selectedItems.includes($(ele).attr('id'))) {
selectedItems.push($(ele).attr('id'));
}
} else {
//pop the element
if(selectedItems.includes($(ele).attr('id'))) {
selectedItems.pop($(ele).attr('id'));
}
}
}
Above function will store the selected row ids in the global variable array
Now add following lines to pjax:end event handler
$(document).on('pjax:end', function () {
//Select the already selected items on the grid view
if(!empty(selectedItems)){
$.each(selectedItems, function (index,value) {
$("#"+value).attr('checked',true);
});
}
});
Hope it helps.
I just solved this problem and it works properly with Pjax.
You may use my CheckboxColumn. I hope this can help. The checked items are recorded with cookies.
You can read the part with //add by hezll to understand how to fix it, because I didn't provide a complete general one.
Hope it works for you.
https://owncloud.xiwangkt.com/index.php/s/dGH3fezC5MGCx4H

MVC 4 Partial view with different model called with AJAX

I'm trying to solve a problem. I am new to MVC and trying to understand how the models work. I get the main page and main model stuff and that if you want to show a partial view the data you show must be part of the main model. This makes the main model pretty large and doesn't that require me to submit the entire model to get the partial view? In any case, let's say I have a list of things and one column is a link. This link calls an AJAX method to get more data and display in a jQuery dialog - my goal. So I would have a call like this:
function showDetails(id) {
$("#divShowDetails").load('#(Url.Action("GetDetails", "Home", null, Request.Url.Scheme))?Id= ' + id);
}
My view is like "_DetailsView.cshtml", defined as a partial view. Does this page need to define the model in the main page or can it be a different model or no model at all? Can I return a ViewData from the controller method, pop open the dialog and fill it with data?
Should the controller method return a PartialViewResult or just an ActionResult? Let's say the details view are details of a part number or something and I want to show a bunch of data elements for the part. Does this have to me a model? I am confused and any help would be greatly appreciated.
Thanks guys. Do you still use the common:
[HttpGet]
public PartialViewResult SelectedItem (string itemId)
{
// gather data for the item
return PartialView(itemModel);
}
And you are saying that the itemModel does not have to be part of the item list model?

yii efullcalendar widget and external events drag and drop not working

Hi I am trying to use drag and drop external events for fullcalendar and get working with the yii extension full calender - which seems to be just a wrapper.
The part that is not working (no errors just does not work) is dragging the external event onto the calendar and it staying there. It drags over but it just returns home.
Reading the fullcalendar docs - it looks like I need to provide a callback function to 'drop' attribute. I've been using the external-event example which is part of full calendar. I did discover the example was using the object name '#calendar' and that yii is creating name '#yw0' but it still didn't work after I updated.
I cannot find a way to get it work. I tried a simple alert which sort of works, it is called on page load - not after a drag operation.
So I declared a variable with the function in View
//$dropcallback=new CJavaScriptExpression("alert('hi')");
$dropcallback=new CJavaScriptExpression(
"function(date, allDay) {
var originalEventObject = $(this).data('eventObject');
var copiedEventObject = $.extend({}, originalEventObject);
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
$('#yw0').fullCalendar('renderEvent', copiedEventObject, true);
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the Draggable Events list
$(this).remove();
}
}
");
Then I create the widgit like this
$this->widget('ext.EFullCalendar.EFullCalendar', array(
'themeCssFile'=>'cupertino/jquery-ui.min.css',
'options'=>array(
'header'=>array(
'left'=>'prev,next',
'center'=>'title',
'right'=>'today'
),
'editable'=>true,
'dropable'=>true,
'drop'=>$dropcallback,
'events'=>Game::model()->gameCalendarData(),
)));
My yii experiance is little and same with JS - so any help appreciated in how to get this working.
I understand that in JS you need to provide a callback to allow the drag op to succeed. But what sort of call back do I need when it is wrapped in a yii widgit? I tried a PHP callback and again it is only called on page load.
The result I wish is that I can build the external events list from the DB - allow users to drag them onto the calendar - and save them in the DB.
I did manage to get data from DB displayed in the calendar.
Thanks
Droppable is spelt with two p's. So
'dropable'=>true,
Should be
'droppable'=>true,

Silverlight localization from database, not resx

I have a Silverlight 4 OOB application which needs localizing. In the past I have used the conventional resx route but I have been asked to follow the architecture of an existing winforms app.
All the strings are currently stored in a database - I use a webservice to pull these down and write them into a local Effiproz Isolated Storage database. On Login I load a Dictionary object with the language strings for the users language. This works fine.
However, I want to automate the UI localization (the WinForms app does it like this):
Loop through all the controls on the page and look for any Textblocks - if there is a text property I replace it with the localized version. If the text is not found, then I WRITE the string to the database for localization.
This works ok on simple forms but as soon as you have expanders/scrollviewers and content controls then the VisualTree parser does not return the children of the controls as they are not necessarily visible (see my code below). This is a known issue and thwarts my automation attempt.
My first question is: Is there a way of automating this on page load by looping through the complex (non-visual) elements and looking up the value in a dictionary?
My second question is: If not, then is the best way of handling this is to load the strings into an app resource dictionary and change all my pages to reference it, or should I look into generating resx files, either on the server (and package it with the app as per normal) or on the client (I have the downloaded strings, can I make and load resx files?)
Thanks for any pointers.
Here is my existing code that does not work on collapsed elements and complex content controls:
public void Translate(DependencyObject dependencyObject)
{
//this uses the VisualTreeHelper which only shows controls that are actually visible (so if they are in a collapsed expander they will not be returned). You need to call it OnLoaded to make sure all controls have been added
foreach (var child in dependencyObject.GetAllChildren(true))
{
TranslateTextBlock(child);
}
}
private void TranslateTextBlock(DependencyObject child)
{
var textBlock = child as TextBlock;
if (textBlock == null) return;
var value = (string)child.GetValue(TextBlock.TextProperty);
if (!string.IsNullOrEmpty(value))
{
var newValue = default(string);
if (!_languageMappings.TryGetValue(value, out newValue))
{
//write the value back to the collection so it can be marked for translation
_languageMappings.Add(value, string.Empty);
newValue = "Not Translated";
}
child.SetValue(TextBlock.TextProperty, newValue);
}
}
Then I have tried 2 different approaches:
1) Store the strings in a normal dictionary object
2) Store the strings in a normal dictionary object and add it to the Application as a Resource, then you can reference it as
TextBlock Text="{Binding Path=[Equipment], Source={StaticResource ResourceHandler}}"
App.GetApp.DictionaryStrings = new AmtDictionaryDAO().GetAmtDictionaryByLanguageID(App.GetApp.CurrentSession.DefaultLanguageId);
Application.Current.Resources.Add("ResourceHandler", App.GetApp.DictionaryStrings);
//http://forums.silverlight.net/forums/p/168712/383052.aspx
Ok, so nobody answered this and I came up with a solution.
Basically it seems that you can load the language dictionary into your global resources using
Application.Current.Resources.Add("ResourceHandler", App.GetApp.DictionaryStrings);
<TextBlock Text="{Binding [Equipment], Source={StaticResource ResourceHandler}}" />
and then access it like a normal StaticResource. We have the requirement of noting all our missing strings into a database for translation - for this reason I chose to use a Converter that calls a Localise extension method (so it can be done on any string in the code behind) which then looks up the string in the Dictionary (not the resource) and can do something with it (write it to a local DB) if it does not exist.
Text="{Binding Source='Logged on User', Converter={StaticResource LocalizationConverter}}"/>
This method works ok for us.