c# How possible geckowebbrowser tr tableto htmal data show in textbox? - gecko

<tr><td colspan="3" class="sms_content">4173 message </td></tr>
I am want html data show in our textbox but I am fail so need help.
Below code I am trying.
GeckoElementCollection tagsCollection = geckoWebBrowser1.Document.GetElementsByTagName("tr");
foreach (GeckoElement currentTag in tagsCollection)
{
if (currentTag.GetAttribute("colspan").Contains("3"))
{
((GeckoHtmlElement)currentTag).GetAttribute(textBox36.Text);
delay(300);
}
else
{
}
}
It's really important for me so if you provide any better solution then it's really great for me & also for all.

Looks like in your foreach loop you are iterating through TR elements, not TD. So when you are trying to get attribute, it returns nothing, because TR does not have it. Try this:
var tagsCollection = Browser.Document.GetElementsByTagName("tr");
foreach (var tr in tagsCollection) // iterate through TR
{
foreach (var td in tr.ChildNodes) // iterate through TD
{
if (td.GetAttribute("colspan").Contains("3"))
{
var attr = td.GetAttribute(textBox36.Text);
// some other code
}
}
}

Related

How can I pass Dictionary<string, dynamic> to a blazor component?

I am trying to pass a dictionary as a parameter to a blazor component. The dictionary needs to store <string, dynamic>, <string, List>, and <string, Dictionary<string, dynamic>> key-value pairs.
I tried to do this, but get the error, "'EventCallbackFactory' has no applicable method named 'CreateBinder' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched."
Is what I am trying to do valid, and if not, why? Is there another way I should approach this?
Here is the code for my blazor component, for reference:
#page "/dictitemcomponent"
#using System.Collections.Generic;
<ul>
#foreach (KeyValuePair<string, dynamic> item in thisDict)
{
#if(item.Value.GetType() == typeof(Dictionary<string, dynamic>))
{
<li>#item.Key.ToString() : </li>
#foreach (var dict in item.Value)
{
<DictItemComponent thisDict=dict/>
}
}
#if(item.Value.GetType() == typeof(List<dynamic>))
{
<li>#item.Key.ToString() : </li>
#foreach (var value in item.Value)
{
<li>#value</li>
}
}
#if(item.Value.GetType() != typeof(List<dynamic>) && item.Value.GetType() != typeof(Dictionary<dynamic, dynamic>))
{
<li>#item.Key.ToString() : <input #bind="item.Value"/></li>
}
}
</ul>
#code
{
public KeyValuePair<string, dynamic> newProperty = new KeyValuePair<string, dynamic>();
[Parameter] public Dictionary<string,dynamic> thisDict {get; set;}= new Dictionary<string, dynamic>();
//convert the value of a KVP to a dictionary
public void ValueToProperty(KeyValuePair<string,dynamic> property)
{
string key = property.Key;
property = new KeyValuePair<string, dynamic>(key, new Dictionary<string, dynamic>());
}
public void ValueToList(KeyValuePair<string,dynamic> property)
{
string key = property.Key;
property = new KeyValuePair<string, dynamic>(key, new List<dynamic>());
}
}
May I know what you are trying to achieve?
Based on your first if statement, why would you have a dictionary inside a dictionary?
By reading your exception and your 3rd conditional statement, it seems that you are trying to bind the input to your dictionary value. However, this is not how you should use a dictionary. Unless you are binding to the usual "type" property (e.g. string), you may use #bind=someVariable. Otherwise, in a dictionary, each value should tie to their respective key and therefore, #bind=_dict[key] ("shorthand" syntax for #bind-value and #bind-value:event) instead of binding input to the item.value. For easier understanding, I've scoped out the aforementioned conditional statement and simulated a solution to the problem in the following lines. It should render value in the <label> next to the input during onchange:
#page "/dict"
#foreach (var kvp in _dict)
{
<div>
<label>#kvp.Key</label>
<input #bind=_dict[kvp.Key] />
<label>Key:#kvp.Key|Value:#kvp.Value</label>
}
#code {
private Dictionary<string, string> _dict = new()
{
["1"] = "One",
["2"] = "Two",
["3"] = "Three",
["4"] = "Four",
["5"] = "Five",
};
}
Meanwhile, you should simplify your if statements as follow:
#if(item.Value.GetType() == typeof(Dictionary<string, dynamic>))
{
//dowork
}
else if(item.Value.GetType() == typeof(List<dynamic>))
{
//do more work
}
else
{
//do other work
}
Screenshot for my Input fields rendered based on Key Value Pair and value entered

Property values of the same type are updated incorrectly in Blazor

Background:
I wanted to achieve the following:
Keep a copy of the data context and use the copy for editing
So that I can reset the data context back to its unchanged state using an onclick event by doing copyValue = unchangedValue
Here is my attempt (it's been trimmed down in size to reduce noises but it has the same issue):
**index.razor**
#page "/"
#using SolutionName.Data
#using System.Reflection
<EditForm Model="Items2">
<table class="table">
<thead>
<tr>
<th>Summary</th>
</tr>
</thead>
<tbody>
#foreach (var i in Items2)
{
<tr #key="#i.GetHashCode()">
<InputText #bind-Value="i.Summary"></InputText>
</tr>
}
</tbody>
</table>
</EditForm>
//
//reflections for debuggings
//
#if (Items != null)
{
<p>
#foreach (var item in Items)
{
<span>#($"Items.{typeof(WeatherForecast).GetProperty(nameof(WeatherForecast.Summary)).Name}={typeof(WeatherForecast).GetProperty(nameof(WeatherForecast.Summary)).GetValue(item)}")</span>
}
</p>
}
#if (Items2 != null)
{
<p>
#foreach (var item in Items2)
{
<span>#($"Items2.{typeof(WeatherForecast).GetProperty(nameof(WeatherForecast.Summary)).Name}={typeof(WeatherForecast).GetProperty(nameof(WeatherForecast.Summary)).GetValue(item)}")</span>
}
</p>
}
#code{
List<WeatherForecast> Items = new List<WeatherForecast>();
List<WeatherForecast> Items2 = new List<WeatherForecast>();
protected override void OnInitialized()
{
Items = new List<WeatherForecast>()
{
new WeatherForecast()
{
Date = DateTime.Now,
Summary = "123",
TemperatureC = 1
}
};
Items2 = Items;
}
private void ResetItems2()
{
Items2 = Items;
}
}
As you can see, I am binding Items2, and not Items, to the <EditForm>.
However, updating the summary seems to update both Items2 and Items. I also noticed that this will not happen if Items and Items2 are of two different types (say that they have exactly the same properties, and I cast one to another...)
Two questions:
Why is Item updated in this case?
Is there a way to only update Items2 and not Items, while allowing Items and Items2 to be the same type?
Detailed steps to reproduce the issue:
Step 1. Initialized and render for the first time
Step 2. Change the value to 456 and then tab away
The expected result should be
Items.Summary=123 (not 456)
Items2.Summary=456
The issue is that you're using reference type assignment. When you assign Items to Items2, you actually assign a pointer to Itemss values. Both variable point to the same list of objects.
If it's applicable create a value type instead. Saving data in the local storage and then retrieving it is a viable solution.
This:
List<WeatherForecast> Items = new List<WeatherForecast>();
List<WeatherForecast> Items2 = new List<WeatherForecast>();
is superfluous. Code like this:
List<WeatherForecast> Items;
List<WeatherForecast> Items2;

Editor method of HtmlHelper class doesn't work with collections

In my view I have a model with a property Details of type List. The collection has 3 elements. Now I need to edit this list in a view.
If I use Html.EditorFor method passing the expression everything works correctly, But if I use Html.Editor method, the binding fails. By "fails" I mean that MVC uses the string editor for all fields (even if they are numbers) passing null as a model.
// this works correctly
#for (var i = 0; i < Model.Details.Count; i++)
{
<li>
#Html.EditorFor(m => m.Details[i].Name)
#Html.EditorFor(m => m.Details[i].Age)
</li>
}
// this doesn't work
#for (var i = 0; i < Model.Details.Count; i++)
{
<li>
#Html.Editor("Details[" + i +"].Name")
#Html.Editor("Details[" + i +"].Age")
</li>
}
I'm using ASP.NET Core 3.0 and didn't test this code against previous versions. For several reasons, I cannot use the EditorFor method so I'm stuck with this problem.
Any ideas?
Editor() HTML Helper method is for simple type view and EditorFor() HTML Helper method is for strongly type view to generate HTML elements based on the data type of the model object’s property.
The definition of Html.Editor:
// Summary:
// Returns HTML markup for the expression, using an editor template. The template
// is found using the expression's Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata.
//
// Parameters:
// htmlHelper:
// The Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper instance this method extends.
//
// expression:
// Expression name, relative to the current model. May identify a single property
// or an System.Object that contains the properties to edit.
//
// Returns:
// A new Microsoft.AspNetCore.Html.IHtmlContent containing the <input> element(s).
//
// Remarks:
// For example the default System.Object editor template includes <label> and <input>
// elements for each property in the expression's value.
// Example expressions include string.Empty which identifies the current model and
// "prop" which identifies the current model's "prop" property.
// Custom templates are found under a EditorTemplates folder. The folder name is
// case-sensitive on case-sensitive file systems.
public static IHtmlContent Editor(this IHtmlHelper htmlHelper, string expression);
You could identify a single property for the expression of Editor Tag Helper like below :
#model MVC3_0.Models.Detail
<table>
<tr>
<td>Id</td>
<td>#Html.Editor("Id")</td>
</tr>
<tr>
<td>Name</td>
<td>#Html.Editor("Name")</td>
</tr>
<tr>
<td>Age</td>
<td>#Html.Editor("Age")</td>
</tr>
</table>
public IActionResult Index()
{
var model = new Detail { Id = 1, Name = "jack", Age = 12 };
return View(model);
}
Result:
There is a workaround that you could use TextBox or input instead
#for (var i = 0; i < Model.Details.Count; i++)
{
<li>
#Html.TextBox("Details[" + i + "].Name", Model.Details[i].Name, new { htmlAttributes = new { #class = "text-field" } })
#Html.TextBox("Details[" + i + "].Age", Model.Details[i].Age, new { htmlAttributes = new { #class = "text-field" } })
</li>
}
// input tag helper
#for (var i = 0; i < Model.Details.Count; i++)
{
<li>
<input asp-for="#Model.Details[i].Name" />
<input asp-for="#Model.Details[i].Age" />
</li>
}

Copy Google Spreadsheet + Share with same users in script

I have searched the far reaches of the internet for a couple days now, but cannot seem to find a solution to my issue. I have limited knowledge of programming, but if I can get this to work, it is going to do wonderful things.
EXPLANATION: I need to make a copy of a template spreadsheet, using a script inside spreadsheet A and copy over all the permissions of the template into the copy (specifically the name and protected ranges). I am using SheetSpider.
As of right now, I can create the duplicate of the template, but SheetSpider seems to drop the permissions that the template has, and rewrites them with users that you define during the setup process. Instead, I would just like to copy the permissions of the template file. It seems to be tricky because a regular copy of the spreadsheet still does not bring over the permissions for the name and protected range settings like it would if you go to file > copy spreadsheet and check the box that says "and share with the same users" which DOES retain protected range settings.
Again, I have a very limited knowledge of programming, but I think I have pinpointed the lines that seem to drop and reset the permissions. I have tried playing with the below for days now to get it to leave the permissions alone, but to no avail.
Any help or guidance would be greatly appreciated!
Thanks!
function checkFixFileACLs(file, approvedViewers, approvedEditors) {
var viewers = file.getViewers().join(",");
viewers = viewers.split(",");
var editors = file.getEditors().join(",");
editors = editors.split(",");
viewers = arr_diff(editors, viewers);
var owner = file.getOwner().toString();
var fileKey = file.getId();
var driveFile = DriveApp.getFileById(fileKey);
var currViewers = [];
for (var k=0; k<viewers.length; k++) {
if ((viewers[k]!='')&&(approvedViewers.indexOf(viewers[k].toLowerCase())==-1)&&(approvedEditors.indexOf(viewers[k].toLowerCase())==-1)&&(viewers[k]!=owner)) {
try {
call(function() {driveFile.removeViewer(viewers[k].toLowerCase());});
} catch(err) {
Logger.log(err.message);
}
} else {
currViewers.push(viewers[k].toLowerCase());
}
}
for (var k=0; k<approvedViewers.length; k++) {
if ((approvedViewers[k]!='')&&(approvedViewers[k])) {
if (currViewers.indexOf(approvedViewers[k])==-1) {
try {
call(function() {driveFile.addViewer(approvedViewers[k].toLowerCase());});
} catch(err) {
Logger.log(err.message);
}
}
}
}
var currEditors = [];
for (var k=0; k<editors.length; k++) {
if ((editors[k]!='')&&(approvedEditors.indexOf(editors[k].toLowerCase())==-1)&&(editors[k]!=owner)) {
try {
call(function() {driveFile.removeEditor(editors[k].toLowerCase());});
} catch(err) {
Logger.log(err.message);
}
} else {
currEditors.push(editors[k].toLowerCase().replace(/\s+/g, ''));
}
}
for (var k=0; k<approvedEditors.length; k++) {
if ((approvedEditors[k]!='')&&(approvedEditors[k])) {
if (currEditors.indexOf(approvedEditors[k].toLowerCase())==-1) {
try {
call(function() {driveFile.addEditor(approvedEditors[k].toLowerCase().replace(/\s+/g, ''));});
} catch(err) {
Logger.log(err.message);
}
}
}
}
return;
}
Here a script that will copy the spreadsheet with permissions when run. However, it will turn commentators into viewers. This is avoidable with more code but is not very easy because there is no file method for getting commentators.
function myFunction() {
var file = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).makeCopy();
var editors = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getEditors();
for (var i = 0; i<editors.length;i++) {
file.addEditor(editors[i])
}
var viewers = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getViewers();
for (var i = 0; i<viewers.length;i++) {
file.addViewer(viewers[i])
}
}

MVC 4 How to get json response from a repository into a view using Ajax?

I am a newbie when it comes to MVC4 Web Development and there's something I am struggling with.
Basically, I have the following :
public class maincontroller: Controller
{
private MyRepository myRepository;
public mainController()
{
myRepository= new MyRepository();
}
public ActionResult Index()
{
var mystuff = myRepository.GetPrograms();
return View(mystuff);
}
public ActionResult MyStuff()
{
var mystuff = myRepository.GetStuff(1);
return Json(mystuff , JsonRequestBehavior.AllowGet);
}
}
Assuming that in my `MyRepository' class I have two functions:
One that is setting up `mystuff':
public MyRepository()
{
for (int i = 0; i < 8; i++)
{
programs.Add(new MyStuff
{
Title = "Hello" + i,
content = "Hi"
});
}
}
and second function that gets Stuff:
public List<MyStuff> GetStuff(int pageNumber = 0)
{
return stuff
.Skip(pageNumber * pageCount)
.Take(pageCount).ToList();
}
All works well. I mean I am able to iterate through `stuff' and display on a view...
The problem is that I want to display MyStuff() ( which returns Json ) using AJAX and then append all stuff to a view. How do I do that?
I have been beating my head against the wall for about 4 hours now, and can't get this working.
Please any help will be much appreciated.
Thank you.
At the most straightforward level, you can simply append HTML to your document using something like this (assuming you're using JQuery, because it's so much easier):
<div id="container"></div>
// make AJAX call to "MyStuff" action in the current controller
$.get(#Url.Action("MyStuff", function(data) {
// cycle through each item in the response
$.each(data, function(index, item) {
// construct some HTML from the JSON representation of MyStuff
var html = "<div>" + item.StuffProperty + "</div>";
// append the HTML to a container in the current document
$("#container").append(html);
});
});
This adds some HTML for each item in the collection to a container element, using (eg) StuffProperty from the MyStuff class.
Appending HTML manually like this can be a hassle once it gets too complicated -- at that point you should consider using either:
Partial views (return HTML directly from the controller, instead of JSON)
A client-side templating engine like Mustache.js, Underscore.js, etc, to convert JSON into HTML.