I have this code where you are suppose to be able to pick specific file attributes, but for some reason it is acting really weird. Can anyone spot the error(s)?
This is in a form, I am triggering checkAttributes when a file is selected. (string)path is the path to the selected file.
private async void Dropdown_File_Attr_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
try
{
foreach (FileAttributes attr in Enum.GetValues(typeof(FileAttributes)))
if (e.ClickedItem.Text == attr.ToString() && !(bool)e.ClickedItem.Tag)
File.SetAttributes(path, File.GetAttributes(path) | attr);
else if (e.ClickedItem.Text == attr.ToString() && (bool)e.ClickedItem.Tag)
File.SetAttributes(path, File.GetAttributes(path) & ~attr);
checkAttributes(path);
await WaitX(5);
Dropdown_File.ShowDropDown();
Dropdown_File_Attr.ShowDropDown();
}
catch (Exception ex) { MessageBox.Show("An error occured:\n\n" + ex.ToString(), "Error"); }
}
public async Task WaitX(int miliseconds) { await Task.Delay(miliseconds); }
private List<string> getAttributes(string ppath)
{
List<string> result = new List<string>();
FileAttributes attrs = File.GetAttributes(ppath);
if ((attrs & FileAttributes.Archive) == FileAttributes.Archive) result.Add("Archive");
if ((attrs & FileAttributes.Compressed) == FileAttributes.Compressed) result.Add("Compressed");
// This goes on for every attribute
return result;
}
private void checkAttributes(string ppath)
{
foreach (string s in getAttributes(ppath))
foreach (ToolStripDropDownItem item in Dropdown_File_Attr.DropDownItems)
{
if (item.Text == s)
{
item.Image = Resources.check;
item.Tag = true; // isChecked
}
else
{
item.Image = Resources.cross;
item.Tag = false; // isChecked
}
}
}
Just an example:
If in the beginning only Normal is selected, and I select Hidden, Hidden is the only one with a cross. If then select ReadOnly, ReadOnly is the only one with a cross but if I check, the file is still Hidden in Windows Explorer.
I have been looking for the error hours. Can anyone please help me (I don't have a lot of experience with Enums and FileAttributes)?
you loop over all items of the dropdown, but act only on the clicked item. you have to check all of the items. and combine their values to construckt the final attribute value, or you'll never catch the automatically cleared item. or just set the one checked attribute, without combining it with the current flags of the file, id you only want to set the one anyway.
as an aside, your logic would work with multi selection, which i'd allow anyway. it makes sense to allow setting a file hidden and readonly, for example.
Related
I took reference from below Ruslan post and implemented same and working as expected but sometimes, am facing an issue saying like "An error occurred during processing of the field ItemRequiresTerms: There is already an open DataReader associated with this Command which must be closed first."
How to show images inside selector lookup?
One Stock Item may have multiple images and we need only icon images.
Below is the code.
public void InventoryItemRowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
var row = e.Row as InventoryItem;
if (row != null)
{
if (!string.IsNullOrEmpty(row.ImageUrl))
{
foreach (NoteDoc noteDoc in PXSelectReadonly<NoteDoc, Where<NoteDoc.noteID, Equal<Required<NoteDoc.noteID>>>>.Select(Base, row.NoteID)) // here i got error
{
foreach (UploadFile uploadFile in PXSelectReadonly<UploadFile, Where<UploadFile.fileID, Equal<Required<UploadFile.fileID>>>>.Select(Base, noteDoc.FileID))
{
if (uploadFile.Name.Contains("icon"))
{
row.ImageUrl =
ControlHelper.GetAttachedFileUrl(null, uploadFile.FileID.ToString());
break;
}
}
}
}
}
}
You need to use separate connection scope to execute additional BQL statements within a RowSelecting event handler.
More details can be found here.
You can avoid nested for loops by utilizing proper Join,
public void InventoryItemRowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
var row = e.Row as InventoryItem;
if (row != null)
{
if (!string.IsNullOrEmpty(row.ImageUrl))
{
using (new PXConnectionScope())
{
UploadFile uploadFile = PXSelectReadonly2<UploadFile, InnerJoin<NoteDoc, On<NoteDoc.fileID, Equal<UploadFile.fileID>>>,
Where<NoteDoc.noteID, Equal<Required<NoteDoc.noteID>>,
And<UploadFile.name, Like<Required<UploadFile.name>>>>>.
Select(Base, row.NoteID, "%icon%");
row.ImageUrl = (uploadFile != null) ? ControlHelper.GetAttachedFileUrl(null, uploadFile.FileID.ToString())
: null;
}
}
}
}
Already an accepted answer here, but I wanted to show you an alternative to the deeply indented structure you are using in your example code.
public void InventoryItemRowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
var row = e.Row as InventoryItem;
if (row == null)
return; // Don't proceed when row doesn't exist
if (string.IsNullOrEmpty(row.ImageUrl))
return; // Don't proceed when ImageUrl doesn't exist
foreach (NoteDoc noteDoc in PXSelectReadonly<NoteDoc, Where<NoteDoc.noteID, Equal<Required<NoteDoc.noteID>>>>.Select(Base, row.NoteID)) // here i got error
{
foreach (UploadFile uploadFile in PXSelectReadonly<UploadFile, Where<UploadFile.fileID, Equal<Required<UploadFile.fileID>>>>.Select(Base, noteDoc.FileID))
{
if (!uploadFile.Name.Contains("icon"))
continue; // Skip non-icon files
row.ImageUrl = ControlHelper.GetAttachedFileUrl(null, uploadFile.FileID.ToString());
}
}
}
Note how you use more the code page instead of pushing everything over to the right. This is your original example, so it doesn't have the fixes from the accepted answer, I just wanted to show you a possible alternate pattern to consider in the future.
This also is a dramatic change when you apply this to the accepted solution:
public void InventoryItemRowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
var row = e.Row as InventoryItem;
if (row == null)
return; // Don't proceed when row doesn't exist
if (string.IsNullOrEmpty(row.ImageUrl))
return; // Don't proceed when ImageUrl doesn't exist
using (new PXConnectionScope())
{
UploadFile uploadFile = PXSelectReadonly2<UploadFile, InnerJoin<NoteDoc, On<NoteDoc.fileID, Equal<UploadFile.fileID>>>,
Where<NoteDoc.noteID, Equal<Required<NoteDoc.noteID>>,
And<UploadFile.name, Like<Required<UploadFile.name>>>>>.
Select(Base, row.NoteID, "%icon%");
if (uploadFile == null)
continue; // Skip non-icon files
row.ImageUrl = ControlHelper.GetAttachedFileUrl(null, uploadFile.FileID.ToString());
}
}
I have problem making my combobox searching inside the strings in the items.
I want to narrow down a list of members. They are formatted in this way (unique member id) - First name - last name.
When i leave all the settings "as is", then it will only "allow" me to search at the first char in the string.
The DataSource is set from a list, what are made from looping through all the files in a folder.
The code i have been using is as follows(partial code)
private void searchForShooterComboBox_KeyUp(object sender, KeyEventArgs e)
{
//if(e => KeyCode == Keys::Down || e => KeyCode == Keys::Down)
//string comboBoxValue = searchForShooterComboBox.Text;
//searchForShooterComboBox.DataSource = null;
//searchForShooterComboBox.DataSource = fliterComboBox(searchForShooterComboBox, memberFileNames);
//searchForShooterComboBox.Text = comboBoxValue;
}
private void searchForShooterComboBox_TextChanged(object sender, EventArgs e)
{
searchForShooterComboBox.DataSource = null;
searchForShooterComboBox.DataSource = fliterComboBox(searchForShooterComboBox, memberFileNames);
}
private List<string> fliterComboBox(ComboBox cobx, List<string> stringList)
{
List<string> returnList = new List<string>();
if (cobx.Text != ""){
try
{
foreach (string s in stringList)
{
if (s.Contains(cobx.Text))
{
returnList.Add(s);
}
}
}catch{
}
}
return returnList;
}
some of the code i tried seemed to filter the list OK, but after the methods ran it fills what seems to be the first item in the new list into the "text field", so the user wont be able to continue typing a name ex.
Will it make any difference using ComboBox.Items.Add() and ComboBox.Items.Remove() instead of using DataSource?
edit: the comboBox DataSource is initially set in the form_load event handler. Where the following code regarding the combobox is:
searchForShooterComboBox.DropDownStyle = ComboBoxStyle.DropDown;
searchForShooterComboBox.AutoCompleteMode = AutoCompleteMode.Suggest;
searchForShooterComboBox.AutoCompleteSource = AutoCompleteSource.ListItems
Thanks for taking the time to look.
Okay seems i figured something out myself,don't know if its the best way, but seems to get the job done :)
firstly i added the string's into both the ComboBox.items and into a list<string>. The reason for adding them both ways is for the user to see all available options on load.
for (int i = 0; i < membersFiles.Length; i++)
{
searchForShooterComboBox.Items.Add(membersFiles[i].Replace(".txt", "").Replace(#"C:\Users\Nicolai\Desktop\skytter\", "").Replace("-", " "));
memberFileNames.Add(membersFiles[i].Replace(".txt", "").Replace(#"C:\Users\Nicolai\Desktop\skytter\", "").Replace("-", " "));
}
After that i added a combobox_keydown event from the property window.
private void searchForShooterComboBox_KeyDown(object sender, KeyEventArgs e)
{
try
{
//checking if the key pressed is RETURN, in that case try to fill the combobox with the selected item,
//and continuing with other method
if (e.KeyValue == 13)
{
searchForShooterComboBox.Text = (string)searchForShooterComboBox.SelectedItem;
fillInfoInForm();
}
//making sure the key pressed IS NOT DOWN, UP, LEFT, RIGHT arrow key.
else if (e.KeyValue > 40 || e.KeyValue < 37)
{
filterComboBox(searchForShooterComboBox, searchForShooterComboBox.Text);
searchForShooterComboBox.Select(searchForShooterComboBox.Text.Length, 0);
searchForShooterComboBox.DroppedDown = true;
}
}
catch (FileNotFoundException ex) {
MessageBox.Show("Der blev ikke fundet nogen fil med flg. sti " + ex.FileName + "\nHusk at vælge hele navnet i listen, eller skriv det nøjagtigt som det står!");
}
}
made this method to search through the list items, clear the items in the combobox, and add the ones that match.
private void filterComboBox(ComboBox cobx, string enteredSearch)
{
//clearing ComboBox items before adding the items from the LIST that meets the search
cobx.Items.Clear();
//looping over the items from the list, comparing them to the search from the combobox text field.
//if the item in the list does not contain the string searched it will return an index of -1.
for (int i = memberFileNames.Count-1; i >= 0; i--)
{
if (memberFileNames[i].IndexOf(enteredSearch, 0, StringComparison.CurrentCultureIgnoreCase) >= 0)
{
cobx.Items.Add(memberFileNames[i]);
}
}
}
if you are having trouble finding the right KeyValues, try looking at
https://msdn.microsoft.com/en-us/library/system.windows.forms.keyeventargs.keyvalue(v=vs.110).aspx
and copy paste the code from there, and add it to you key_down event handler, and it will show most info(if not all) in a message box.
That was my workaround, if you have a better way of doing it, i am all ears :)
When a user uses the "Insert Link" feature on the RTE to create stories, we get something like...<Item-Name-Of-Story
Instead of taking the Item name I would like to use another field called "Headline"
Does anyone know how to do this?...
Headline-Of-Story
Any help will be much appreciated. Thanks
First of all, you need need to look at this class with Reflector or DotPeek : Sitecore.Shell.Controls.RichTextEditor.InsertLink.InsertLinkForm and to modify it with your own class.
You need to modify just this method,I tested and works fine :
protected override void OnOK(object sender, EventArgs args)
{
Assert.ArgumentNotNull(sender, "sender");
Assert.ArgumentNotNull((object) args, "args");
string displayName;
string text;
if (this.Tabs.Active == 0 || this.Tabs.Active == 2)
{
Item selectionItem = this.InternalLinkTreeview.GetSelectionItem();
if (selectionItem == null)
{
SheerResponse.Alert("Select an item.", new string[0]);
return;
}
else
{
displayName = selectionItem["Headline"];
if (selectionItem.Paths.IsMediaItem)
text = CustomInsertLinkForm.GetMediaUrl(selectionItem);
else if (!selectionItem.Paths.IsContentItem)
{
SheerResponse.Alert("Select either a content item or a media item.", new string[0]);
return;
}
else
{
LinkUrlOptions options = new LinkUrlOptions();
text = LinkManager.GetDynamicUrl(selectionItem, options);
}
}
}
else
{
MediaItem mediaItem = (MediaItem) this.MediaTreeview.GetSelectionItem();
if (mediaItem == null)
{
SheerResponse.Alert("Select a media item.", new string[0]);
return;
}
else
{
displayName = mediaItem.DisplayName;
text = CustomInsertLinkForm.GetMediaUrl((Item) mediaItem);
}
}
if (this.Mode == "webedit")
{
SheerResponse.SetDialogValue(StringUtil.EscapeJavascriptString(text));
base.OnOK(sender, args);
}
else
SheerResponse.Eval("scClose(" + StringUtil.EscapeJavascriptString(text) + "," + StringUtil.EscapeJavascriptString(displayName) + ")");
}
After you modify this class you need to modify next file:
\sitecore\shell\Controls\Rich Text Editor\InsertLink\InsertLink.xml where you need to change codeBeside section
<CodeBeside Type="Sitecore.Shell.Controls.RichTextEditor.InsertLink.InsertLinkForm,Sitecore.Client"/>
with something like :
<CodeBeside Type="YourNameSpace.YourInsertLinkForm,YourAssembly"/>
The simplest way around this would be to type the desired link text, then select this before clicking 'insert link' - this way your hyperlink will have the text of whatever you entered, instead of defaulting to the item name.
If you want to modify how Sitecore renders links in RTE fields, you would need to modify the <renderField> pipeline - if you search for this in the web.config, you will see the different classes involved here. Using dotPeek you can decompile the Sitecore source to see how this works. Potentially you could then create your own renderField pipeline handler to change the link rendering behaviour and then reference this new class in your web.config.
I have a loop going through each of my textboxes in Form1 and getting the tag for them as i will need to compare object IDs. in situations where an object already exist in one of my textboxes, i do not want to allow the user to add this object again, but if this object does not exist in any of the textboxes, only then can the user add this item.
I have tried it with this loop below but it doesnt seem to work as it keeps telling me "Object reference not set to an instance of an object." on this line if (resval.types.xan_ID == tbItems.types.xan_ID)
after i get the message box which i want, how can I change this code to achieve this goal.
// Get the name which will be passed into the textbox
var resval = form2result.getValue();
//go through each of my textbox
foreach (TextBox tb in TextBoxList)
{
var tbItems = (ReportItems)tb.Tag;
if (tb.Text != "")
{
//if the item returned is the same as an item in the textbox
if (resval.types.xan_ID == tbItems.types.xan_ID)
{
// display this message and break out of the loop
MessageBox.Show("You have previously selected this report, please chose another");
break;
}
// otherwise add the item into the textbox.
else
{
// otherwise add name to the textbox
_dict[sender].Text = resval.ToString();
}
}
}
ReportItems
public class ReportItems
{
public DataSet1.xspGetAnalysisTypesRow types { get; set; }
//Analysis types or Reports
public ReportItems(DataSet1.xspGetAnalysisTypesRow analysisTypes)
{
types = analysisTypes;
}
//Return the name of this type.
public override string ToString()
{
return this.types.xan_Name;
}
}
getValueFunction (This is in a different form)
public ReportItems getValue()
{
ReportItems selection = (ReportItems)reportListBx.SelectedItem;
// if user has selected a value
return selection;
}
I'm not sure what the link is between _dict[sender] and TextBoxList but you haven't set the Tag as the same point as setting the text. Assuming these are referring to the same object this will cause an error the next time you use this method as you'll have a text box with no tag.
// Get the name which will be passed into the textbox
var resval = form2result.getValue();
// The user didn't select anything somehow.
if (resval == null)
{
MessageBox.Show("Nothing Selected");
return;
}
// resval hasn't been setup correctly.
if (resval.types == null)
{
MessageBox.Show("Internal Error");
return;
}
Boolean alreadyExists = false;
//go through each of my textbox
foreach (TextBox tb in TextBoxList)
{
var tbItems = (ReportItems)tb.Tag;
//The Textbox must contain text and tbItems must not be null
if (tb.Text != "" && tbItems != null)
{
//The tag has been set, but somehow the types are null?
if (tbItems.types == null)
{
MessageBox.Show("Internal Error");
break;
}
//if the item returned is the same as an item in the textbox
if (resval.types.xan_ID == tbItems.types.xan_ID)
{
alreadyExists = true;
// display this message and break out of the loop
MessageBox.Show("You have previously selected this report, please chose another");
break;
}
// otherwise add the item into the textbox.
}
}
if (!alreadyExists)
{
// otherwise add name to the textbox
_dict[sender].Text = resval.ToString();
//set the tag?
_dict[sender].Tag = tbItems;
}
// Get the name which will be passed into the textbox
var resval = form2result.getValue();
ArrayList arrayList = new ArrayList();
//go through each of my textbox
foreach (TextBox tb in TextBoxList)
{
var tbItems = (ReportItems) tb.Tag;
if (tb.Text != "") return;
//if the item returned is the same as an item in the textbox
/* Try this if the below line doesnt work
if(string.IsNullOrEmpty(resval.types.xan_ID) || string.IsNullOrEmpty(tbItems.types.xan_ID) return;
if (resval.types.xan_ID == tbItems.types.xan_ID) return;
*/
if ((string)(resval.types.xan_ID) == (string)(tbItems.types.xan_ID)) return;
// otherwise add the item into the textbox.
// otherwise add name to the textbox
arrayList.Add(resval.ToString());
}
foreach (var arr in arrayList)
{
// something = arr.ToString();
}
You can handle onmouseover or onclick event of a Textbox(on which user focus to add) by using jquery and can check whether a user add an object to previous Textboxes or not.
I'm creating a custom web user control in c#. It is intended to interact with a permission hierarchy. We have different "sites" and each site has many "apps" and each app has many "permissions"
So, We have a TabPanel that loads a tab for each site. Then in each tab we have a TreeView where the parent nodes are the apps and the inner nodes are the permissions.
The Permissions show check boxes based on some criteria and are checked based on whether or not the HasPermission function returns true.
All of this code works...but only for the first user selected. For any subsequent user chosen, a step through the debugger shows all the correct logic being executed, but the page displays the same information as that of the first user selected.
So basically, it's saving the display somewhere...and I'm at a loss to find out where.
public partial class Permissions : System.Web.UI.UserControl
{
string _NTLogin;
CoreUser _User;
bool _IsAdmin;
public string NTLogin
{
get
{
return _NTLogin;
}
set
{
ViewState["NTLogin"] = value;
_NTLogin = value;
}
}
public bool IsAdmin
{
get
{
return _IsAdmin;
}
set
{
ViewState["IsAdmin"] = value;
_IsAdmin = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
public void LoadTabs()
{
string [] sites = MISCore.BusinessLayer.CorePermission.GetSites();
foreach (string site in sites)
{
TabPanel tp = new TabPanel();
tp.HeaderText = site;
TabContainer1.Tabs.Add(tp);
}
}
public void LoadTrees()
{
if(_User == null)
return;
TabPanelCollection tabs = TabContainer1.Tabs;
foreach (TabPanel tab in tabs)
{
string site = tab.HeaderText;
string[] apps = MISCore.BusinessLayer.CorePermission.GetApplications(site);
TreeView tv1 = new TreeView();
tv1.EnableViewState = false;
foreach (string app in apps)
{
TreeNode tn1 = new TreeNode(app);
tn1.SelectAction = TreeNodeSelectAction.None;
string[] perms = MISCore.BusinessLayer.CorePermission.GetPermissions(site, app);
foreach (string perm in perms)
{
TreeNode tcn1 = new TreeNode(perm);
tcn1.SelectAction = TreeNodeSelectAction.None;
if (IsAdmin || _User.Manager.HasPermission(site, app, perm))
{
tcn1.ShowCheckBox = true;
if (_User.HasPermission(site, app, perm))
{
tcn1.Checked = true;
}
else
{
tcn1.Checked = false;
}
}
else
{
tcn1.ShowCheckBox = false;
}
tn1.ChildNodes.Add(tcn1);
}
tv1.Nodes.Add(tn1);
}
tab.Controls.Add(tv1);
}
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
_NTLogin = (string)ViewState["NTLogin"];
_IsAdmin = (bool)ViewState["IsAdmin"];
if(_NTLogin != null)
_User = new CoreUser(_NTLogin);
TabContainer1.Tabs.Clear();
LoadTabs();
LoadTrees();
}
}
[UPDATE]
I iterate through the treeview after all the above code, it correctly stores their correct status. This is an issue with displaying. I can successfully change any other property, tooltip, text, etc to display their state, but the checkboxes are not updating...
I would use Fiddler to see who is caching the results. By looking at the requests you'll be able to tell if it's the browser or the server causing the problem.
Or if its okay with your client, you can put in a small link button that says refresh, and either you or the user can force this refresh treeview method, whenever required.
Should be pretty simple, in the paramters for the tab just add EnableViewState = false. Let me know if this works for you.