unity can't destroy child object - unity3d

I want to delete a specific child object, but it just won't get destroyed. I even tried 4 different ways to destroy it but none of them worked. Strangely, I dont get any errors in the console.
DestroyImmediate(prefabParent.GetComponent<Transform>().GetChild(Select.instance.ID).gameObject);
Destroy(prefabParent.GetComponent<Transform>().GetChild(Select.instance.ID).gameObject);
DestroyImmediate(prefabParent.transform.GetChild(Select.instance.ID).gameObject);
Destroy(prefabParent.transform.GetChild(Select.instance.ID).gameObject);
this is how Select looks like
public static Select instance;
public int ID;
private void Awake()
{
instance = this;
}
public void SetTarget(int _ID)
{
ID = _ID;
}
extra information:
this script is meant to delete a button prefab from a dynamic scrollview

This isn't pretty efficient but can't we use loops and check each?
foreach (Transform child in transform)
{
if (child.gameObject.GetInstanceID() == ID)
{
Destroy(child.gameObject);
break;
}
}

Related

ViewModels references in ShellViewModel Caliburn.Micro

In this thread : Can anybody provide any simple working example of the Conductor<T>.Collection.AllActive usage? I've had part of an answer but I'm still a but confused.
I would simply like to reference all my view models into my ShellViewModel to be able to open/close ContentControls, but without injecting all of them in the constructor.
In the answer, it is suggested to inject an interface in the constructor of the ShellViewModel. If I do that, do I have to inject all my ViewModels in a class that implements that interface?
public MyViewModel(IMagicViewModelFactory factory)
{
FirstSubViewModel = factory.MagicallyGiveMeTheViewModelIWant();
SecondSubViewModel = factory.MagicallyGiveMeTheViewModelIWant();
ThirdSubViewModel = factory.MagicallyGiveMeTheViewModelIWant();
Items.Add(FirstSubViewModel);
Items.Add(SecondSubViewModel);
Items.Add(ThirdSubViewModel);
}
Also, I would like to avoid going through IoC.Get<> to get the instances of my view Models, I think it violates the principles of IoC if I am not mistaken.
In a few other examples, they create new viewModels when needed, but what's the point of using IoC in that case, especially when I need services injected inside those new ViewModels?
In my Shell view, I have a layout with 3 different areas, bound to my shell view model by :
<ContentControl x:Name="Header"
Grid.ColumnSpan="3"/>
<ContentControl x:Name="Menu"
Grid.Row="1"/>
<ContentControl x:Name="Main"
Grid.ColumnSpan="3"/>
In my ShellViewModel extending Conductor.Collection.AllActive, I reference the 3 areas like this:
public Screen Menu { get; private set; }
public Screen Header { get; private set; }
public Screen Main { get; private set; }
I would like to be able to change them like so:
Menu = Items.FirstOrDefault(x => x.DisplayName == "Menu");
Header = Items.FirstOrDefault(x => x.DisplayName == "Header");
Main = Items.FirstOrDefault(x => x.DisplayName == "Landing");
All my ViewModels have a DisplayName set in their constructor.
I have tried this but GetChildren() is empty
foreach (var screen in GetChildren())
{
Items.Add(screen);
}
Am I missing something obvious?
Thanks in Advance!
Finally, I managed to find an answer myself. It's all in the AppBootstrapper!
I ended up creating a ViewModelBase for my Screens so that they could all have an IShell property (so that the ViewModels could trigger a navigation in the ShellViewModel) like so:
public class ViewModelBase : Screen
{
private IShell _shell;
public IShell Shell
{
get { return _shell; }
set
{
_shell = value;
NotifyOfPropertyChange(() => Shell);
}
}
}
then in the AppBoostrapper registered them like this :
container.Singleton<ViewModelBase, SomeViewModel>();
container.Singleton<ViewModelBase, AnotherViewModel>();
container.Singleton<ViewModelBase, YetAnotherViewModel>();
then created an IEnumerable to pass as param to my ShellViewModel ctor:
IEnumerable<ViewModelBase> listScreens = GetAllScreenInstances();
container.Instance<IShell>(new ShellViewModel(listScreens));
then passing the IShell to each ViewModels
foreach (ViewModelBase screen in listScreens)
{
screen.Shell = GetShellViewModelInstance();
}
for the sake of completeness, here are my GetAllScreenInstances() and GetShellViewModelInstance() :
protected IEnumerable<ViewModelBase> GetAllScreenInstances()
{
return container.GetAllInstances<ViewModelBase>();
}
protected IShell GetShellViewModelInstance()
{
var instance = container.GetInstance<IShell>();
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
Here's what my ShellViewModel ctor looks like:
public ShellViewModel(IEnumerable<ViewModelBase> screens )
{
Items.AddRange(screens);
}
Hope this can help someone in the future!

Create multiple objects for an object

I have a Students class as below. My aim is to create multiple student objects and assign a couple of marks for each student. The former is done, but the latter-to assign marks for each student object- is confusing for me. As you can see, I also define a Marks class, but I don't know how to create multiple mark objects for each student object. Thanks for your help.
public class Students {
private int ID;
public Marks mark;
public static int total Student=1;
public Students(int id)
{
this.ID=id;
total Student++;
}
public void enter_Score(double s){
mark =new Marks(s);
}
public void get_Score()
{
print(mark.get_Score());
}
}
public class Marks {
public static int total_marks;
private double Score;
public Marks(double score)
{
this.set_Score(score);
}
public double get_Score() {
return Score;
}
public void set_Score(double score) {
Score = score;
}
}
Depending on whether or not you know how many marks a student will have, all you should have to do is create an array of Mark objects.
public Marks[] marks;
If you don't know how many marks a student will have:
public ArrayList<Marks>() marks;
Then, depending on which one you use, your method may look like:
public void enter_Score(double s)
{
marks.Add(new Marks(s));
}
If you just use an array, you'll have to know which index you want to insert at and how big the array is. Also, remember to initialize the array or ArrayList of Marks in your constructor.

Registering component in autofac

I'm new to autofac(using 2.1.14.854),and im still trying to put my head around in trying to understand
I have an interface and there are one or more implementations to this interface, and the implementation(s) should be fired in a specific sequence.
For example:
public IPipeline
{
void execute();
}
public MyPipeLine_1:IPipeline
{
public void execute(){}
}
public MyPipeLine_2:IPipeline
{
public void execute(){}
}
foreach(IPipeline pipeline in pipelines)
pipeline.execute();
The order execution of IPipeline should be MyPipleLine_2,MyPipleLine_1, etc
I have two questions
1) how to register all the components, that implements IPipeLine interface in a assembly and place them in a List
2) can i define the order of the execution of these components whilst registering
Thanks in advance.
[A quick note: You're using a really old version of Autofac. You may need to update to get the features I'm talking about.]
The first part is easy - Autofac implicitly supports IEnumerable<T>. Just register all the types and resolve:
var builder = new ContainerBuilder();
builder.RegisterType<MyPipeLine_1>().As<IPipeline>();
builder.RegisterType<MyPipeLine_2>().As<IPipeline>();
var container = builder.Build();
var containsAllPipelineComponents = container.Resolve<IEnumerable<IPipeline>>();
It'd be better if you can take it as an IEnumerable<T> rather than a list, but if you have to have a list, you could add a registration for it:
builder
.Register(c => new List<IPipeline>(c.Resolve<IEnumerable<IPipeline>>()))
.As<IList<IPipeline>>();
The second part isn't as easy. Autofac doesn't necessarily guarantee the order of the items in the list. If you need to order them, you'll need to put some sort of ordering metadata on them - attributes, properties, something that you can use to order the pipeline after the fact.
Alternatively, if your pipeline has "stages" or "events" where different components are applicable, look at the design of your pipeline and have a different pipeline interface per event. Within the event it shouldn't matter what order each item executes in. (This is similar to how event handlers in .NET work now. You'd want to mimic that behavior - different events for different stages in the overall lifecycle, but within each specific stage the order of execution of handlers doesn't matter.)
An example might look like:
public interface IFirstStage
{
void Execute();
}
public interface ISecondStage
{
void Execute();
}
public interface IThirdStage
{
void Execute();
}
public class PipelineExecutor
{
public IEnumerable<IFirstStage> FirstHandlers { get; private set; }
public IEnumerable<ISecondStage> SecondHandlers { get; private set; }
public IEnumerable<IThirdStage> ThirdHandlers { get; private set; }
public PipelineExecutor(
IEnumerable<IFirstStage> first,
IEnumerable<ISecondStage> second,
IEnumerable<IThirdStage> third)
{
this.FirstHandlers = first;
this.SecondHandlers = second;
this.ThirdHandlers = third;
}
public void ExecutePipeline()
{
this.ExecuteFirst();
this.ExecuteSecond();
this.ExecuteThird();
}
public void ExecuteFirst()
{
foreach(var handler in this.FirstHandlers)
{
handler.Execute();
}
}
// ExecuteSecond and ExecuteThird look just
// like ExecuteFirst, but with the appropriate
// set of handlers.
}
Then when you register your handlers it's simple:
var builder = new ContainerBuilder();
builder.RegisterType<SomeHandler>().As<IFirstStage>();
builder.RegisterType<OtherHandler>().As<IFirstStage>();
builder.RegisterType<AnotherHandler>().As<ISecondStage>();
// You can have any number of handlers for any stage in the pipeline.
// When you're done, make sure you register the executor, too:
builder.RegisterType<PipelineExecutor>();
And when you need to run the pipeline, resolve and run.
var executor = container.Resolve<PipelineExecutor>();
executor.ExecutePipeline();
This is just like event handlers but not using delegates. You have a fixed order of pipeline "events" or "stages" but the handlers inside each stage aren't guaranteed order.
If you need to modify the pipeline to have more stages, yes, you'll need to modify code. Just like if you had a new event you wanted to expose. However, to add, remove, or change handlers, you just modify your Autofac registrations.
I suggest you to use Metadata feature.
It gives you an advantage to define the order on registration stage.
Here is an example:
internal class Program
{
private static void Main(string[] args)
{
var builder = new ContainerBuilder();
var s1 = "First";
var s2 = "Second";
var s3 = "Third";
builder.RegisterInstance(s1).As<string>().WithMetadata<Order>(c => c.For(order => order.OrderNumber, 1));
builder.RegisterInstance(s2).As<string>().WithMetadata<Order>(c => c.For(order => order.OrderNumber, 2));
builder.RegisterInstance(s3).As<string>().WithMetadata<Order>(c => c.For(order => order.OrderNumber, 3));
using (var container = builder.Build())
{
var strings = container.Resolve<IEnumerable<Meta<string, Order>>>();
foreach (var s in strings.OrderBy(meta => meta.Metadata.OrderNumber))
{
Console.WriteLine(s.Value);
}
}
Console.ReadKey();
}
public class Order
{
public int OrderNumber { get; set; }
}
}

How can I marry AutoCompleteBox.PopulateComplete method with the MVVM paradigm?

Here is the setup:
I have an autocompletebox that is being populated by the viewmodel which gets data from a WCF service. So it's quite straightforward and simple so far.
Now, I am trying to follow the principles of MVVM by which the viewmodel doesn't know anything about the view itself. Which is good, because I bound the Populating event of the autocomplete box to a method of my viewmodel via triggers and commands.
So the view model is working on fetching the data, while the view is waiting. No problems yet.
Now, the view model got the data, and I passed the collection of results to a property bound to the ItemSource property of the control. Nothing happens on the screen.
I go to MSDN and to find the officially approved way on how this situation is supposed to be handled (http://msdn.microsoft.com/en-us/library/system.windows.controls.autocompletebox.populating(v=vs.95).aspx):
Set the MinimumPrefixLength and MinimumPopulateDelay properties to
values larger than the default to minimize calls to the Web service.
Handle the Populating event and set the PopulatingEventArgs.Cancel
property to true.
Do the necessary processing and set the ItemsSource property to the
desired item collection.
Call the PopulateComplete method to signal the AutoCompleteBox to show
the drop-down.
Now I see a big problem with the last step because I don't know how I can call a method on a view from the view model, provided they don't know (and are not supposed to know!) anything about each other.
So how on earth am I supposed to get that PopulateComplete method of view called from the view model without breaking MVVM principles?
If you use Blend's Interactivity library, one option is an attached Behavior<T> for the AutoCompleteBox:
public class AsyncAutoCompleteBehavior : Behavior<AutoCompleteBox>
{
public static readonly DependencyProperty SearchCommandProperty
= DependencyProperty.Register("SearchCommand", typeof(ICommand),
typeof(AsyncAutoCompleteBehavior), new PropertyMetadata(null));
public ICommand SearchCommand
{
get { return (ICommand)this.GetValue(SearchCommandProperty); }
set { this.SetValue(SearchCommandProperty, value); }
}
protected override void OnAttached()
{
this.AssociatedObject.Populating += this.PopulatingHook;
}
protected override void OnDetaching()
{
this.AssociatedObject.Populating -= this.PopulatingHook;
}
private void PopulatingHook(object sender, PopulatingEventArgs e)
{
var command = this.SearchCommand;
var parameter = new SearchCommandParameter(
() => this.AssociatedObject
.Dispatcher
.BeginInvoke(this.AssociatedObject.PopulateComplete),
e.Parameter);
if (command != null && command.CanExecute(parameter))
{
// Cancel the pop-up, execute our command which calls
// parameter.Complete when it finishes
e.Cancel = true;
this.SearchCommand.Execute(parameter);
}
}
}
Using the following parameter class:
public class SearchCommandParameter
{
public Action Complete
{
get;
private set;
}
public string SearchText
{
get;
private set;
}
public SearchCommandParameter(Action complete, string text)
{
this.Complete = complete;
this.SearchText = text;
}
}
At this point you need to do 2 things:
Wire up the Behavior
<sdk:AutoCompleteBox MinimumPopulateDelay="250" MinimumPrefixLength="2" FilterMode="None">
<i:Interaction.Behaviors>
<b:AsyncAutoCompleteBehavior SearchCommand="{Binding Search}" />
</i:Interaction.Behaviors>
</sdk:AutoCompleteBox>
Create a DelegateCommand which handles your aysnc searching.
public class MyViewModel : ViewModelBase
{
public ICommand Search
{
get;
private set;
}
private void InitializeCommands()
{
this.Search = new DelegateCommand<SearchCommandParamater>(DoSearch);
}
private void DoSearch(SearchCommandParameter parameter)
{
var client = new WebClient();
var uri = new Uri(
#"http://www.example.com/?q="
+ HttpUtility.UrlEncode(parameter.SearchText));
client.DownloadStringCompleted += Downloaded;
client.DownloadStringAsync(uri, parameter);
}
private void Downloaded(object sender, DownloadStringCompletedEventArgs e)
{
// Do Something with 'e.Result'
((SearchCommandParameter)e.UserState).Complete();
}
}

SmartGWT Object binding without specifying object's fields

I am just wondering if it's possible to create some sort of binding without explicitly specifying all of the fields that need to be mapped to some widget(i.e. ListGrid).
Currently I do the following: First I read all the JSON objects fields and put these fields into CategoryRecord object like this:
public class CategoryRecord extends Record {
public CategoryRecord(String displayName, String id) {
setDisplayName(displayName);
setId(id);
}
private void setId(String id) {
setAttribute("id", id);
}
public String getId() {
return getAttributeAsString("id");
}
private void setDisplayName(String displayName) {
setAttribute("displayName", displayName);
}
public String getDisplayName() {
return getAttributeAsString("displayName");
}
}
Then I return a CategoryRecord[] object and put it into a ListGrid. But what if application developers decide to change the "id" field to "categoryId" or completely remove it. Do I have to manually change my code each time something like this happens? Or is there a way to get the whole JSON object, get it's fields and put it wherever I want, without specifying their names.
Thanks in advance!
Just iterate over the properties of the JSON object and create ListGridField objects for each one.