Create default childs to node in umbraco - c#

I'm trying to find out how to force node to create only one node child of other type ?
I have 'hotel' node and i want to add one 'rooms' node and one 'facilities' node ('rooms' create 'room' and 'facilities' create 'facility')
by default when i will create hotel the system will create this 2 folders or to force him that he can create only one each
I prefer to do it with the management system (if possible) but code behind be good also !
Thanks in advance for all helpers!

As far as I am concerned, I do not know a way to achieve this by means of the Umbraco backoffice.
However, you can use the ContentService Events in order to cancel the creation of that particular page if it has been already created. The ContentServiceSaving method will fire up each time that you try to create a node in the CMS.
public class ContentServiceEventsController : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentService.Saving += ContentServiceSaving;
}
private void ContentServiceSaving(IContentService sender, SaveEventArgs<IContent> e)
{
switch (e.Entity.ContentType.Alias)
{
case "RoomsDocumentTypeAlias":
case "FacilitiesDocumentTypeAlias":
// Do your logic to detect if your Hotel node "Hilton eilat queen of sheba"
// already contains either a Rooms node or a Facilities node underneath.
// If so, cancel the creation of the event of a new one.
e.Cancel = true;
break;
default:
break;
}
}

Related

Is this an alright method for buttons?

I'm practicing with buttons in Unity and I'm trying to figure out how I can assign different methods to a button without using the OnClick thing in the inspector so I came up with this.
public class UIButtons : MonoBehaviour
{
void Start()
{
var buttons = FindObjectsOfType<Button>(); //I should probably have this outside of this method
foreach (Button button in buttons)
{
button.onClick.AddListener(() => ButtonPressed(button));
}
}
void ButtonPressed(Button button)
{
switch (button.name)
{
case "MMPlayButton": //The main menu play button
Debug.Log("Play button pressed");
break;
case "PlayButton":
Debug.Log("Play button pressed");
break;
case "SettingsButton":
Debug.Log("Settings button pressed");
break;
case "QuitButton":
Debug.Log("Quit button pressed");
break;
default:
Debug.LogWarning("Button doesn't have a case: " + button.name);
//could do some kind of pop up message saying the button pressed isn't available or something
break;
}
}
}
I know this can work, however, I'd imagine this is a horrible way to do things because it's using the name so if I were to change the name or make a typo it breaks, or an issue I did encounter was if buttons have the same name, and if I add more buttons I'd have to add more cases and then it would probably turn out to be a giant mess.
I could be wrong though and maybe this is an alright idea, but I doubt it so looking for some help with this.
You can simplify this by using inheritance. Create a base class for all of your buttons to use, ie. UIButtonBase that has the OnButtonPressed virtual method. Then create specific buttons that inherit this base class and override the OnButtonPressed method.
Base Class
public class UIButtonBase: MonoBehaviour
{
protected virtual void Awake()
{
var button = GetComponent<Button>();
if (button)
{
button.onClick.AddListener(() => OnButtonPressed());
}
else
{
Debug.Log(name + " does not have a Button component!");
}
}
protected virtual void OnButtonPressed()
{
Debug.Log("UIButtonBase::OnButtonPressed()");
}
}
Specific implementation of a button
public class SettingsButton : UIButtonBase
{
protected override void OnButtonPressed()
{
Debug.Log("SettingsButton::OnButtonPressed()");
// If you want the base functionality as well, add..
//
base.OnButtonPressed();
}
}
For setup, create a button and add this script to it. You may need to change the GetComponent in Awake (UIButtonBase) to GetComponentInParent or GetComponentInChildren, depending on your gameobjects hierarchy. You could also expose the Button component in the UIButtonBase script and use that reference.
I know this won't be a good answer but if I were you, I would make different files for different buttons. Like SettingButton.cs, PlayButton.cs etc.
This approach will not add a huge amount of burden to your code but as the functionalities of your buttons increase, this approach will greatly help to keep your code organized.

Behavior Tree: How/When to return "running" state on leaf nodes?

I've implemented a simple Behavior Tree algorithm which I intend to use inside a Unity project. It's mostly working as I expected, except I'm having trouble making proper use of it, which might be caused by some misunderstanding of mine. My problem is as follows:
If a leaf node takes a long time to finish, for instance, an action that makes a game unit follow a specific path, that means the leaf node is currently at the "running" state. However, if I return the state, I can no longer run the rest of the function, which means I can't reach my destination.
So my question is: what is the proper way to tell my tree that a leaf node is running?
Here's what I got on my ActionNode class:
public class ActionNode : BTNode
{
public delegate NodeStates ActionNodeDelegate();
protected ActionNodeDelegate nodeAction;
public ActionNode(ActionNodeDelegate action)
{
nodeAction = action;
}
public override NodeStates Evaluate()
{
switch (nodeAction())
{
case NodeStates.FAILURE:
currentNodeState = NodeStates.FAILURE;
return currentNodeState;
case NodeStates.SUCESS:
currentNodeState = NodeStates.SUCESS;
return currentNodeState;
case NodeStates.RUNNING:
currentNodeState = NodeStates.RUNNING;
return currentNodeState;
default:
currentNodeState = NodeStates.FAILURE;
return currentNodeState;
}
}
}
If you need to check the other classes, it's all based on this article. Linking it for the sake of keeping the thread cleaner.
As for an action example, consider this:
private NodeStates FollowPath() {
bool targetReached;
if (targetReachable)
targetReached = WalkToTarget();
if (targetReached)
return NodeStates.SUCESS;
else
return NodeStates.FAILURE;
}
What I'm wondering is, if WalkToTarget takes a long time, how do I return a "running" state?
I've read many different articles on the subject, but I can't seem to grasp the exact concept behind these states. I understand how I can, for instance, tell that a Sequence or Selector node is running.
The only idea that crossed my mind is that I'd store the remaining path inside a variable at my enemy class and call the method every game update tick, but I feel like that's just poor coding.
Are leaf nodes supposed to return "running" at any given moment? If so, in which cases would that happen? Any examples would be appreciated!
Okay, I figured out what I was doing wrong. I was assuming that my tree was responsible for executing the action code, when it is actually supposed to only evaluate the state of every node. In this case, my above example would change to something like this:
private NodeStates ShouldFollowPath() {
if (targetReachable && this.position != target.position)
return NodeStates.RUNNING;
else if (this.position == target.position)
return NodeStates.SUCESS;
else
return NodeStates.FAILURE;
}
And then I'd check the state of the above Node after evaluating the tree and execute my FollowPath code:
private ActionNode FollowPathNode = new ActioNode(ShouldFollowPath);
private void Update()
{
FollowPathNode.evaluate();
if (FollowPathNode.nodeState == NodeStates.RUNNING)
FollowPath();
}
In summary, I misunderstood the usage of the behavior tree. The above example solves my problems.

ObservableCollection as base Class c#

I have a class that is derived from ObservableCollection as listed below
public class Accounts : ObservableCollection<Account>
{
public Accounts(){}
// some code
// mode plus plus code
}
at other place i have
Accounts.CollectionChanged += Accounts_CollectionChanged;
Now whenever i change/update or add any thing in Account , the below event fires and things are fine so far.
void Accounts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
MessageBox.Show("Add");
break;
case NotifyCollectionChangedAction.Remove:
MessageBox.Show("Remove");
break;
case NotifyCollectionChangedAction.Replace:
MessageBox.Show("Replace");
break;
case NotifyCollectionChangedAction.Reset:
MessageBox.Show("Reset");
break;
}
}
However my problem (its painful) is the First event it gives me is 'Reset' always, no matter what i do (update any value in account or add another account). Then if there are 2 items in collection, 'Add' event will fire two times but Replace event DOESN'T Fire.
Second problem i am having is (kind of first problem) if i add any thing to the collection and if there are 4 items already in the collection it generates 'Add' event 5 times (first 4 times for existed items and 5th one for new item) and i am not sure what am if doing wrong or i don't know how to fix it. Any idea what needs to be done to handle this?
Any help will be appreciated

Recursively Call an Event C#

I'm looking for a method to call an event recursively. I have the following
private void btn_choose_Click(object sender, EventArgs e)
{
// switch statement to take the user input and decide the outcome.
switch (Convert.ToInt32(nud_cat_chooser.Value))
{
case 1:
if (Convert.ToInt32(lbl_p1_cat_1_value.Text) == Convert.ToInt32(lbl_p2_cat_1_value.Text))
{
MessageBox.Show("Stalemate");//message box to inform the user of a statemate.
playingcards card1 = player1.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
playingcards card2 = player2.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
assign_Values();
btn_choose_Click();
}
....
}
}
I want to call the btn_choose_click event again to sort out the stalemate. The labels will be given the values from the assign method. But I'm struggling on implementing the call for btn_choose_click(); What arguments must I pass? Can anyone show me an example?
Thanks :)
Pass sender and e.
However, if I were you, I would simply pull the logic out of your handler and put it into a method. It is a decidedly bad practice to call a handler explicitly. The event handler is supposed to respond to an event. If you were to put a break point in your handler, you'd expect it only to be hit while debugging in response to the event in handles, not because some other method elsewhere in your class called it. E.g.:
private void btn_choose_Click(object sender, EventArgs e)
{
NewMethod();
}
private void NewMethod()
{
switch (Convert.ToInt32(nud_cat_chooser.Value))
{
case 1:
if (Convert.ToInt32(lbl_p1_cat_1_value.Text) == Convert.ToInt32(lbl_p2_cat_1_value.Text))
{
MessageBox.Show("Stalemate");//message box to inform the user of a statemate.
playingcards card1 = player1.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
playingcards card2 = player2.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
assign_Values();
NewMethod();
}
You can simply call Button.PerformClick(). I don't know the name of your button. This will fire your method.
See also Button.PerformClick() method at MSDN.
This method can be called to raise the Click event.
You are going into a land of recursivity, take great care!
Do not call the method directly. This is a bad design. Create a different function, and make it obvious this is a recursive function.
private void btn_choose_Click(object sender, EventArgs e)
{
int action = Convert.ToInt32(nud_cat_chooser.Value);
this.DequeuePlayer(action);
}
/// <summary>
/// Recursivly called until there is no more cards
/// </summary>
private void DequeuePlayer(int action)
{
// switch statement to take the user input and decide the outcome.
switch (action)
{
case 1:
if (Convert.ToInt32(lbl_p1_cat_1_value.Text) == Convert.ToInt32(lbl_p2_cat_1_value.Text))
{
MessageBox.Show("Stalemate");//message box to inform the user of a statemate.
playingcards card1 = player1.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
playingcards card2 = player2.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
assign_Values();
this.DequeuePlayer(action);
}
....
}
Extract the data from the UI before calling functions. Separate the layer of your logic
Do not launch MessageBox.Show in a middle of nowhere
Test the value of the property Text of you text box. User can put anything in that.
In this case you can just call as
btn_choose_Click(this, new EventArgs());
But be very careful, the sender is to be used to identify which button is calling the event... Now that you are violating it, you must write proper documentation to mention not to rely on the sender and eventargs parameter inside the event.
Also you can think of write a new method and calling it using a loop... That would be more readable and reliable..
I'd do the thing in a while loop. Making it recursive unnecessarily just makes the code more confusing.
private void btn_choose_Click(object sender, EventArgs e)
{
var continuing= true;
while (continuing)
{
// switch statement to take the user input and decide the outcome.
switch (Convert.ToInt32(nud_cat_chooser.Value))
{
case 1:
if (Convert.ToInt32(lbl_p1_cat_1_value.Text) == Convert.ToInt32(lbl_p2_cat_1_value.Text))
{
MessageBox.Show("Stalemate");//message box to inform the user of a statemate.
playingcards card1 = player1.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
playingcards card2 = player2.Dequeue();//creates tempoary instance of the abstract class playign cards to store the cards
assign_Values();
}
....
case end state:
do something
continuing= false;
}
}
}
You can create separate method from the above code. You can than call them from events and wherever you want.
Simply use:
btn_choose_Click(null, null);
As long as you are not relying on the sender param in your method. You can even extract a function from your code and invoke it in the onClick event.

C# Treeview Indexing

I've got a bit of a problem with treeview and how the indexing of nodes works. In my program, I have a database that can contain any amount of users. Each user is separated by a carriage return (i.e. one user per line). I'm creating a treeview object that lists all users in the database. If the user clicks on a specific node, how do I refer to that node / handle it being selected, as I am dynamically making nodes from the database?
StreamReader getMembers = new StreamReader(#"[data]\db\users.db");
List<string> mems = new List<string>();
members.Nodes.Add("Members");
while (!getMembers.EndOfStream)
{
mems.Add(getMembers.ReadLine());
}
foreach (string o in mems)
{
TreeNode n = new TreeNode(o);
members.Nodes[0].Nodes.Add(n);
}
Database & Program:
If you are trying to get the tree node that was selected you can achieve that by the TreeView.SelectedNode property... (http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.selectednode.aspx)
if you want to handle an event on treenode selected register the TreeView.AfterSelect event (http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.afterselect)
example:
private void TreeView1_AfterSelect(System.Object sender,
System.Windows.Forms.TreeViewEventArgs e)
{
// Vary the response depending on which TreeViewAction
// triggered the event.
switch((e.Action))
{
case TreeViewAction.ByKeyboard:
MessageBox.Show("You like the keyboard!");
break;
case TreeViewAction.ByMouse:
MessageBox.Show("You like the mouse!");
break;
}
}
Assuming you are using the standard forms treeview, it sounds like you want to subscribe to the event on the TreeView.AfterSelect.
// Handle the After_Select event.
private void TreeView1_AfterSelect(System.Object sender,
System.Windows.Forms.TreeViewEventArgs e)
{
// If (TreeView1.SelectedNode...
}

Categories

Resources