我明白你在尝试什么,但我不确定这是做事的正确方式。您的资源对象包含一些可观察对象,但可观察对象的意义在于,当您更改它们时,您之前绑定的 UI 会更改以反映可观察对象中的更改。我的困惑是您的资源应该是静态的。
然后我看到您正在绑定到这些资源,但是您绑定按钮文本的方法被硬编码为使用 StrResources.BtnAdd 资源;如果您将该 observable 更新为“已选择”,则绑定到 StrResources.BtnAdd 的所有按钮都将更改为具有“已选择”的文本。
您真正需要的是一种为每个按钮指定文本的方法,而不是将所有按钮绑定到一个 observable。
阅读您问题的字里行间,我实现了一个simple grid here,我认为它符合您的要求:
http://jsbin.com/finucabo/1/edit?html,js,output
感兴趣的部分是:
var model = {
grid: {
row: ko.observableArray(),
selected: ko.observable()
},
buttonText: function (row) {
return model.grid.selected() === row ? 'Selected' : 'Add';
},
buttonClick: function (row) {
if (model.grid.selected() === row) {
model.grid.selected(null);
} else {
model.grid.selected(row);
}
}
};
还有绑定:
<!-- ko foreach: grid.row -->
<tr>
<td data-bind="text: first"></td>
<td data-bind="text: last"></td>
<td data-bind="text: email"></td>
<td>
<button
type="button"
data-bind="click: $root.buttonClick, text: $root.buttonText($data)">
</button>
</td>
</tr>
<!-- /ko -->
请注意,单击按钮只是将当前行存储到 model.grid.selected observable 中。这将导致 buttonText 重新评估文本绑定。
希望对你有所帮助。
编辑:
关于能够选择多行,您可以将 selected 更改为可观察数组。
我在这里更新了 jsbin:http://jsbin.com/finucabo/2/edit
变化是:
// Helper function added.
function arrayContains(anArray, aValue) {
return ko.utils.arrayFirst(anArray(), function (v) {
return v === aValue;
}) !== null;
}
var model = {
grid: {
row: ko.observableArray(),
// Now using an observable array.
selected: ko.observableArray()
},
buttonText: function (row) {
// Modify to use observable array.
return arrayContains(model.grid.selected, row) ? 'Selected' : 'Add';
},
buttonClick: function (row) {
// Modify to use observable array.
if (arrayContains(model.grid.selected, row)) {
model.grid.selected.remove(row);
} else {
model.grid.selected.push(row);
}
}
};