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