我希望在其他地方为我的表插入待办事项时触发CollectionChanged。
我有一个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>
另一种选择是从应用程序触发我的Hub中的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
再次获取数据。
如果在不刷新整个网站的情况下将新项目添加到azure表中,如何在客户端上更新我的列表?
希望你明白我的目标。 BR
答案 0 :(得分:0)
另一种选择是在服务器而不是客户端设置间隔。
像:
public class MyHub : Hub
{
private ObservableCollection<TodoItem> persons;
public MyHub()
{
Intervalla();
}
public async Task Intervalla()
{
EasyTimer.SetInterval(async () =>
{
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());
}, 1000);
}
这可能是智能/呃选项吗?