In my Windows Phone app, I have a parent class file inherriting from UserControl, and multiple objects inheriting from that class. So the parent class, Parent.cs, is not partial.
Subclasses, are xaml objects, with xaml file and cs file.
I want to enable movements for all children, and am thus trying to achieve this in parent class.
Here is my code:
this.MoveObjectX = new DoubleAnimation();
this.MoveObjectY = new DoubleAnimation();
this.MoveObjectX.Duration = TimeSpan.FromMilliseconds(100);
this.MoveObjectY.Duration = TimeSpan.FromMilliseconds(100);
this.RenderTransform = new CompositeTransform();
Storyboard.SetTarget(this.MoveObjectX, this.RenderTransform);
Storyboard.SetTarget(this.MoveObjectY, this.RenderTransform);
Storyboard.SetTargetProperty(
this.MoveObjectX,
new PropertyPath(CompositeTransform.TranslateXProperty));
Storyboard.SetTargetProperty(
this.MoveObjectY,
new PropertyPath(CompositeTransform.TranslateYProperty));
this.storyboardMoveObject = new Storyboard();
this.storyboardMoveObject.Children.Add(this.MoveObjectX);
this.storyboardMoveObject.Children.Add(this.MoveObjectY);
this.storyboardMoveObject.Completed += new EventHandler(storyboardMoveObject_Completed);
But it does not work. Code complies and runs, but the children won't move.
I must add that in each child, I set the doubleanimations from and to numbers.
Thanks for your help.
If the code to do the movement is called from the constructor of the parent as you mention in the comments, you need to call the parent's constructor in the constructors of the children. It is not automatic, that is why your code never gets called for the children.
The easiest way to called the parent's constructor is to append base()
public child():base() { ... }
Alright got my own error: I was replacing RenderTransform with some other transform in sub classes. I just started to use a TransformGroup and everything works fine!
Thanks for your help
Related
I have a project created using the clean architecture template.
If I want a domain event be raised when a new project is created, where do I add that?
If I have to raise an event whenever a new item be added to a project, I can accomplish that in the Project entity as shown here.
Similarly for MarkCompletion of a ToDoItem as done here.
But its not clear where do I put the code to raise an event when a new Project is created?
One option is doing something like the following in Create End Point here.
newProject.Events.Add(new ProjectCreatedEvent(newProject));
But this is in UI, away from the domain model, and so does not feel right.
The other option is using ef core interceptors. So when ever save changes is called, just raise event as appropriate something like here.
And if I add event in Project ctor, then this is triggered even in case of an update.
public Project(string name)
{
Name = Guard.Against.NullOrEmpty(name, nameof(name));
var newProjectCreatedEvent = new NewProjectCreatedEvent(this);
Events.Add(newProjectCreatedEvent);
}
Are there any better options/patterns?
Any pointer is deeply appreciated.
When you need to raise a domain event on project creation I would create a factory method that publishes the event.
You can use a static method or implement a factory object.
public class Project : BaseEntity, IAggregateRoot
{
public static Project newProject(string name)
{
var project = new Project(name);
var newProjectCreatedEvent = new NewProjectCreatedEvent(project);
Events.Add(newProjectCreatedEvent);
return project;
}
private Project(string name)
{
Name = Guard.Against.NullOrEmpty(name, nameof(name));
}
}
my code is pretty simple, but im quite new to unity... im trying to make it so i can drop my items on the ground when i drag the out of my inventory, but cant quite manage to do so, with a few consistent errors. I have a prefab (just learned of those today), which im trying to change its sprite renderer and spawn it. Heres my code:
public class ItemWorld : MonoBehaviour
{
private Transform prefab;
private Item item;
private SpriteRenderer spriteRenderer;
void Start()
{
prefab = Resources.Load("Prefabs/pfItemWorld") as GameObject;
//myPrefab = Resources.Load("Prefabs/pfItemWorld");
}
public static ItemWorld spawnItemWorld(Vector3 position, Item item)
{
Transform transform = Instantiate(prefab, position, Quaternion.identity);
ItemWorld itemWorld = transform.GetComponent<ItemWorld>();
itemWorld.SetItem(item);
return itemWorld;
}
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
public void SetItem(Item item)
{
this.item = item;
Rect spriteRect = new Rect(0, 0, item.itemIcon.width, item.itemIcon.height);
Sprite mySprite = Sprite.Create(item.itemIcon, spriteRect, new Vector2(0.5f, 0.5f));
spriteRenderer.sprite = mySprite;
}
}
My problem is i cant manage to load my prefab and use it in Instantiate without many errors...
What is wrong with my code?
Here are the errors:
(1) Assets\Scripts\ItemWorld.cs(12,18): error CS0029: Cannot implicitly convert type 'UnityEngine.GameObject' to 'UnityEngine.Transform' (yes, i know what this means, but how can i use a prefab without transform)
(2)Assets\Scripts\ItemWorld.cs(17,43): error CS0120: An object reference is required for the non-static field, method, or property 'ItemWorld.prefab'
I have tried to research but this is my last hope xd
Ill be happy for ANY help,
thanks ahead,
Gambizon
Prefabs are GameObjects and need to be instantiated and declared as such. private transform prefab should be private GameObject prefab.
After you've instantiated the object with
GameObject prefabObject = Instantiate(prefab, position, Quaternion.identity);
You can then use Transform transform = prefabObject.transform; to get the transform component of your newly instantiated prefab.
Also, if you make the prefab reference in the script public, and have this script attached to a GameObject, you can drag the prefab into the inspector so that you don't need Resources.Load("Prefabs/pfItemWorld") as GameObject, as the reference will already be there before run time.
I want an embedded view to be able to call a function from the parent view, so I'm trying to have the child reference its parent by injection. This seems to work fine as long as the embedded view is created onDock:
class TestView : View() {
override val root = vbox {
label("Parent Label")
}
init {
println("Parent is instantiating.")
}
override fun onDock() {
val child = find(TestView2::class)
root.add(child)
}
fun doThing() {
println("Parent is doing a thing.")
}
}
class TestView2 : View() {
val parentClass: TestView by inject()
override val root = hbox {
label("Sub-view label 1")
label("Sub-view label 2")
}
init {
println("Sub-view is instantiating.")
parentClass.doThing()
}
}
I'd like it to be cleaner though. I'd prefer it if I was able to use the find function while creating the parent root. That's a problem, as calling the child view within any part of the init process creates a circular instantiation loop. Any way to avoid this or will I just have to settle for onDock and deal with it?
EDIT:
Just to note, I tried the onDock method again in a real, more complicated application and I got a cycle detection error. So even that method is not guaranteed to work.
You can create cyclic dependencies, but you can't call functions in both component's init block, as that would be impossible to resolve. The main takeaway here is that you're probably doing something you shouldn't. Views should not communicate with each other directly. This creates a tight coupling and prevents reuse. Instead you should communicate with one of the following:
State from a ViewModel
Controller function calls
Events using the EventBus
Since your code example is made up, it's not known what exactly you're trying to achieve in your actual app, but you will find the correct approach in the list above.
I see the urge to call functions in views and setting data directly into ui components instead of using bindings a lot, and in absolutely every case there is a much better way to solve the problem :)
I am facing the following problem,
I have an object called "data". It has three properties, one of it being itemRendererData. The "itemRendererData" is an ArrayCollection of objects having many properties one of which is the property "imageURL" (datatype:String).
I am working in flex. I have defined the view and the item renderer properly. The view has the data. I am supposed to get the images from the url specified by imageURL property.
In the itemRenderer, I have declared, source
source = {data.itemRendererData.imageURL}
But the images are not being displayed.
Use a the FlexEvent.DATA_CHANGE handler rather than binding, which is actually the proper way to handle this and gives you far more control.
public function CustomItemRenderer() {
this.addEventListener(FlexEvent.DATA_CHANGE, this.dataChangeHandler);
this.addEventListener(FlexEvent.CREATION_COMPLETE, this.creationCompleteHandler);
}
private function creationCompleteHandler(e:FlexEvent) {
if (this.data) {
this.image.source = this.data.itemRendererData.imageURL;
}
}
private function dataChangeHandler(e:FlexEvent) {
if (this.data && this.initialized) {
this.image.source = this.data.itemRendererData.imageURL;
}
}
You will notice that I have a handler for FlexEvent.CREATION_COMPLETE as well. This is because the data is actually set before the components are created. So the first time a renderer is loaded, this.image is null and this.image.source will error out.
If that doesn't work, you also need to make sure that the Image/BitmapImage is not a direct child of the renderer. I never did figure out why this was, but adding it as a child of Group fixed that issue where the image was being set but not rendering. Again, I have no idea why this was and I tested for a few hours trying to figure it out.
As an added tip, avoid MXML-based ItemRenderers in mobile applications. They are noticeably slower than pure-AS3 renderers.
I am getting up to speed on Composite WPF, building a small demo app to work through the issues. My app has one region, and two modules, Module A and Module B. Each module contains a simple "Hello World" text block. Both modules are set up as load-on-demand, as per this MSDN How-To.
The shell has two buttons, "Load Module A" and "Load Module B". When a button is clicked, the corresponding module is loaded. So, lets say I click "Load Module A", then "Load Module B". Module A, then Module B load as expected. But if I click "Load Module A" again, nothing happens.
I'm stuck at this point. I think my problem is that I need to activate and deactivate the views in the modules, rather than using load-on-demand. But I have no idea how to do that, and I can't find any documentation or blogs that talk about it.
So, here's my question: How to I load/unload (or show/hide) views? If someone can point me to sample code, I'd really appreciate it. Thanks for your help.
I found my answer. Here is the approach: Load all the modules at startup, then activate and deactivate views as you need them. I am going to write this issue up as a CodeProject article, but here is an outline of how to do it:
(1) In the module Initialize() method, add the module, but don't activate it:
public void Initialize()
{
// Get main region
var mainRegion = m_RegionManager.Regions["MainRegion"];
// Load Module B
var newView = new ModuleBView();
mainRegion.Add(newView, "ModuleA.ModuleAView");
}
Note that the Add() method has two parameters. The second parameter is the name of the view, which we set to the value produced by the ToString() method of the view. We'll see why in the next step.
(2) When activating a view, we need to deactivate the previous view. But we may not know the name of the view, so we deactivate all active views:
public static void ClearRegion(IRegion region)
{
// Get existing view names
var oldViewNames = new List<string>();
foreach (var v in region.Views)
{
var s = v.ToString();
oldViewNames.Add(s);
}
// Remove existing views
foreach (var oldViewName in oldViewNames)
{
var oldView = region.GetView(oldViewName);
region.Deactivate(oldView);
}
}
Since we set the name of each view equal to its ToString() value, we can get the names easily without knowing anything about them in advance.
(3) Now we activate the new view. I do it in an MVVM ICommand.Execute() method:
public void Execute(object parameter)
{
// Get main region
var mainRegion = m_ViewModel.RegionManager.Regions["MainRegion"];
// Clear region
ModuleServices.ClearRegion(mainRegion);
// Activate Module A view
var moduleAView = mainRegion.GetView("ModuleA.ModuleAView");
mainRegion.Activate(moduleAView);
}
Hopefully, that will be enough to get you going. Like I said, I plan to do a more complete writeup, with demo code, for CodeProject.
David Veeneman
Foresight Systems