0
我希望CollectionChanged在從我的表中爲其他地方的Azure插入todo項目時觸發。SignalR KnockoutJS和AzureTodo OnChangeEvent
我有一個mobileapp,我可以通過TodoItemManager插入項目。 我有一個網站列出項目。
現在我想不刷新網站,項目應該被添加。
一個選項是有一個setInterval,但我不喜歡那個選項。
<div class="products">
<div class="row" data-bind="template: { name: 'productTemplate', foreach: products }">
</div>
<span class="messageClass" style="color: red;"></span>
</div>
<script type="text/html" id="productTemplate">
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<div class="caption">
<h3 data-bind="text: name"></h3>
</div>
</div>
</div>
</script>
<script>
$(function() {
//debugger;
function productViewModel(id, name) {
this.productId = id;
this.name = ko.observable(name);
var self = this;
}
function productListViewModel() {
//debugger;
this.hub = $.connection.myHub;
this.products = ko.observableArray([]);
var products = this.products;
this.init = function() {
this.hub.server.getAllProducts();
}
this.hub.client.getAllProducts = function (allProducts) {
//debugger;
var mappedProducts = $.map(allProducts, function (item) {
//debugger;
return new productViewModel(item.ProductId, item.Name)
});
products(mappedProducts);
}
}
var vm = new productListViewModel();
ko.applyBindings(vm);
$.connection.hub.start(function() {
vm.init();
}).done(function() {
});;
});
</script>
另一種選擇是觸發方法GetAllProducts從應用我的樞紐,因此會引發
await Clients.All.getAllProducts(vm.Products.ToArray());
但我不喜歡這種做法。
我想知道如何更新我的網頁上列出的數據,當我向Azure表中添加項目而不刷新瀏覽器時。
這裏是我的樞紐
public class MyHub : Hub
{
private ObservableCollection<TodoItem> persons;
public MyHub()
{
}
public async Task GetAllProducts()
{
var data = await GetLogs();
VoteViewModel vm = new VoteViewModel();
vm.Products = data.Select(m => new Products() { Name = m.Name }).ToList();
//vm.Products = new List<Products>() { new Products() { Name = "Sample", ProductId = 1 } };
await Clients.All.getAllProducts(vm.Products.ToArray());
}
private async Task<List<TodoItem>> GetLogs()
{
persons = await TodoItemManager.DefaultManager.GetTodoItemsAsync();
persons.CollectionChanged += this.OnCollectionChanged;
return persons.ToList();
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
}
class VoteViewModel
{
public List<Products> Products { get; set; }
}
public class Products
{
public int ProductId { get; set; }
public string Name { get; set; }
}
}
而且在TodoItemManager一看:
public partial class TodoItemManager
{
static TodoItemManager defaultInstance = new TodoItemManager();
MobileServiceClient client;
#if OFFLINE_SYNC_ENABLED
IMobileServiceSyncTable<TodoItem> todoTable;
#else
IMobileServiceTable<TodoItem> todoTable;
#endif
const string offlineDbPath = @"localstore.db";
private TodoItemManager()
{
this.client = new MobileServiceClient(AzureSettings.ApplicationURL);
#if OFFLINE_SYNC_ENABLED
var store = new MobileServiceSQLiteStore(offlineDbPath);
store.DefineTable<TodoItem>();
//Initializes the SyncContext using the default IMobileServiceSyncHandler.
this.client.SyncContext.InitializeAsync(store);
this.todoTable = client.GetSyncTable<TodoItem>();
#else
this.todoTable = client.GetTable<TodoItem>();
#endif
}
public static TodoItemManager DefaultManager
{
get
{
return defaultInstance;
}
private set
{
defaultInstance = value;
}
}
public MobileServiceClient CurrentClient
{
get { return client; }
}
public bool IsOfflineEnabled
{
get { return todoTable is Microsoft.WindowsAzure.MobileServices.Sync.IMobileServiceSyncTable<TodoItem>; }
}
public async Task<ObservableCollection<TodoItem>> GetTodoItemsAsync(bool syncItems = false)
{
try
{
#if OFFLINE_SYNC_ENABLED
if (syncItems)
{
await this.SyncAsync();
}
#endif
IEnumerable<TodoItem> items = await todoTable
.Where(todoItem => !todoItem.Done)
.ToEnumerableAsync();
return new ObservableCollection<TodoItem>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(@"Invalid sync operation: {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(@"Sync error: {0}", e.Message);
}
return null;
}
public async Task SaveTaskAsync(TodoItem item)
{
if (item.Id == null)
{
await todoTable.InsertAsync(item);
}
else
{
await todoTable.UpdateAsync(item);
}
}
#if OFFLINE_SYNC_ENABLED
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
await this.client.SyncContext.PushAsync();
await this.todoTable.PullAsync(
//The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
//Use a different query name for each unique query in your program
"allTodoItems",
this.todoTable.CreateQuery());
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
// Simple error/conflict handling. A real application would handle the various errors like network conditions,
// server conflicts and others via the IMobileServiceSyncHandler.
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
//Update failed, reverting to server's copy.
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change.
await error.CancelAndDiscardItemAsync();
}
Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
}
}
}
#endif
}
如你本身在我中心我
this.OnCollectionChanged
嘗試,但這樣只會改變如果
private ObservableCollection<TodoItem> persons;
變化,這將不會發生,所以我需要調用再次
GetTodoItemsAsync
獲取數據。
如何在不刷新整個網站的情況下將新項目添加到天藍色表格時在客戶端上更新我的列表?
希望你明白我在哪裏瞄準。 BR