• 0

[C#/WPF] Animate a UserControl


Question

Hello gang,

I am learning WPF and I need to animate a UserControl that has been added during runtime

XAML


<Window x:Class="BediaNVMain.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="515" Width="1598" ShowInTaskbar="False" Topmost="True" WindowState="Maximized" WindowStyle="None" Background="#FF001900" xmlns:my="clr-namespace:BediaMenu;assembly=BediaMenu">
<Canvas Name="BediaCanvas"
<Grid Name="BediaGrid" Loaded="BediaGrid_Loaded">
</Grid>
</Canvas>
</Window>
[/CODE]

C# code to add UserControl (BediaMenu.BMenu)

[CODE]
var bmnuBediaMenu = new BediaMenu.BMenu();
bmnuBediaMenu.Margin = new Thickness(40, MenuTop, 40, 20);
bmnuBediaMenu.MenuText = MenuTitle;
bmnuBediaMenu.Height = this.MenuSize;
bmnuBediaMenu.Width = this.ActualWidth - 80;
this.BediaGrid.Children.Add(bmnuBediaMenu);
[/CODE]

I attempted to use the code from this page: http://stackoverflow.com/questions/4214155/wpf-easiest-way-to-move-image-to-x-y-programmatically But when it gets to the last line; story.Begin(this); it errors with this statement: "'BediaMenu' name cannot be found in the name scope of 'BediaNVMain.MainWindow'." I have attempted several options... but with no success.

Any thoughts?

Link to comment
https://www.neowin.net/forum/topic/1051139-cwpf-animate-a-usercontrol/
Share on other sites

Recommended Posts

  • 0
  On 13/01/2012 at 17:25, ~Johnny said:

It looks like you're not actually telling it to look for this instance of the object - you should be passing in the variable name of the object instead (in this case, bmnuBediaMenu), not BediaMenu.

I am using bmnuBediaMenu... I should have included the code that I affected from that url. So here it is (feel free to slap me and tell me; "NO dumbass, it's.....)


Storyboard story = new Storyboard();
DoubleAnimation dbWidth = new DoubleAnimation();
dbWidth.From = bmnuBediaMenu.Width;
dbWidth.To = 600;
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(2.25));
DoubleAnimation dbHeight = new DoubleAnimation();
dbHeight.From = bmnuBediaMenu.Height;
dbHeight.To = 400;
dbHeight.Duration = dbWidth.Duration;
story.Children.Add(dbWidth);
Storyboard.SetTargetName(dbWidth, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
story.Children.Add(dbHeight);
Storyboard.SetTargetName(dbHeight, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
DoubleAnimation dbCanvasX = new DoubleAnimation();
dbCanvasX.From = 0;
dbCanvasX.To = 5;
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbCanvasY = new DoubleAnimation();
dbCanvasY.From = 0;
dbCanvasY.To = 5;
dbCanvasY.Duration = dbCanvasX.Duration;
story.Children.Add(dbCanvasX);
Storyboard.SetTargetName(dbCanvasX, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(dbCanvasY);
Storyboard.SetTargetName(dbCanvasY, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
story.Begin(this);
[/CODE]

  • 0
  On 13/01/2012 at 17:32, ~Johnny said:

You haven't given your menu a name? Set bmnuBediaMenu.Name to something (You're trying to set a storyboard target to this name, but it hasn't got one)

You were correct, I did not give it a name. (now called "FirstMenu") However adding a name did not affect the error. I now get: 'FirstMenu' name cannot be found in the name scope of 'BediaNVMain.MainWindow'.

I FEEL like it has something to do with the Storyboard not properly linking into the location of bmnuBediaMenu... but I do not really know.

btw: Thanks for your time.

I thought I should post the entire function, just in case


private void LoadBediaMenu(string MenuTitle, double MenuTop)
{
try
{
var bmnuBediaMenu = new BediaMenu.BMenu();

bmnuBediaMenu.Margin = new Thickness(40, MenuTop, 40, 20);
bmnuBediaMenu.Name = "FirstMenu";
bmnuBediaMenu.MenuText = MenuTitle;
bmnuBediaMenu.Height = this.MenuSize;
bmnuBediaMenu.Width = this.ActualWidth - 80;
this.BediaGrid.Children.Add(bmnuBediaMenu);


Storyboard story = new Storyboard();
DoubleAnimation dbWidth = new DoubleAnimation();
dbWidth.From = bmnuBediaMenu.Width;
dbWidth.To = 600;
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(2.25));
DoubleAnimation dbHeight = new DoubleAnimation();
dbHeight.From = bmnuBediaMenu.Height;
dbHeight.To = 400;
dbHeight.Duration = dbWidth.Duration;
story.Children.Add(dbWidth);
Storyboard.SetTargetName(dbWidth, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
story.Children.Add(dbHeight);
Storyboard.SetTargetName(dbHeight, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
DoubleAnimation dbCanvasX = new DoubleAnimation();
dbCanvasX.From = 0;
dbCanvasX.To = 5;
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25));
DoubleAnimation dbCanvasY = new DoubleAnimation();
dbCanvasY.From = 0;
dbCanvasY.To = 5;
dbCanvasY.Duration = dbCanvasX.Duration;
story.Children.Add(dbCanvasX);
Storyboard.SetTargetName(dbCanvasX, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(dbCanvasY);
Storyboard.SetTargetName(dbCanvasY, bmnuBediaMenu.Name);
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
story.Begin(this);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
[/CODE]

  • 0
  On 13/01/2012 at 17:45, articuno1au said:

this.BediaGrid.Children.Add(bmnuBediaMenu);

I think you need to look another layer deeper.

EDIT:: It's entirely possible I am misreading this. I'm struggling with your var names D:

Do you mean, for example, this line


Storyboard.SetTargetName(dbCanvasX, bmnuBediaMenu.Name);
[/CODE]

Should be like this:

[CODE]
Storyboard.SetTargetName(dbCanvasX, this.BediaGrid.bmnuBediaMenu.Name);
[/CODE]

The problem with that is the code cannot find the bmnuBediaMenu as during compile time it is not within the Grid.

  • 0

Yeah, you will need to obtain it with something like this.

BediaMenu temp = new BediaMenu();
temp = BediaGrid.GetChild(<type/name>);[/CODE]

Sorry, it's pretty shoddy pseudocode.

Then operate on temp. That's the best way to do it I can think of.

Is there any reason you are adding it programatically instead of "hard coding" it?

  • 0
  On 13/01/2012 at 17:51, articuno1au said:

Yeah, you will need to obtain it with something like this.

BediaMenu temp = new BediaMenu();
temp = BediaGrid.GetChild(<type name="">);[/CODE]

Sorry, it's pretty shoddy pseudocode.

Then operate on temp. That's the best way to do it I can think of.

Is there any reason you are adding it programatically instead of "hard coding" it?

I will look into getting the object reference (thanks, no worries about the pcode)

The reason that the menus are loaded programatically as opposed to in the XAML is that the number of menus varies based on the user's screen height and the height of the menu (which can be changed by the user) If you want to see where this is going you can see version 1 of Bedia at my site http://www.blissgig.com/display.aspx?id=13

  • 0

Looks interesting..

God damn @ the new IPB text editor. It keeps changing code bits into stupid things D:

The only painful thing about working with programatically generated interfaces is you have to .GetObject/Child/BananaPeel to do anything.

EDIT:: Congrats on evolving from VB.net to C# :p You feel more manly already don't you? :p

  • 0
  On 13/01/2012 at 18:00, articuno1au said:

EDIT:: Congrats on evolving from VB.net to C# :p You feel more manly already don't you? :p

I starting playing with c# back in 2001, but since all my jobs since then have been with VB there has not been a big deal to change over. I tend to be tech-agnostic. Whatever offers the better job, that's what I care about. There are some things I miss about VB, ie: the Intelisense does not work as well.. but nbd.

I tried this code, but still the same error ('FirstMenu' name cannot be found in the name scope of 'BediaNVMain.MainWindow'.) What dumba$$ thing am I doing?


private void LoadBediaMenu(string MenuTitle, double MenuTop)
{
try
{
var bmnuBediaMenu = new BediaMenu.BMenu();

bmnuBediaMenu.Margin = new Thickness(40, MenuTop, 40, 20);
bmnuBediaMenu.Name = "FirstMenu";
bmnuBediaMenu.MenuText = MenuTitle;
bmnuBediaMenu.Height = this.MenuSize;
bmnuBediaMenu.Width = this.ActualWidth - 80;
this.BediaGrid.Children.Add(bmnuBediaMenu);

foreach (UIElement element in this.BediaCanvas.Children)
{
if (element is Grid)
{
Grid grd = element as Grid;
foreach (UIElement mnuElement in grd.Children)
{
if (mnuElement is BediaMenu.BMenu)
{
BediaMenu.BMenu bMenu = mnuElement as BediaMenu.BMenu;
if (bMenu.Name == "FirstMenu")
{
//Animation Test 02
Storyboard story = new Storyboard();
DoubleAnimation dbWidth = new DoubleAnimation();
dbWidth.From = bMenu.Width;
dbWidth.To = 600;
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(2.25));
DoubleAnimation dbHeight = new DoubleAnimation();
dbHeight.From = bMenu.Height;
dbHeight.To = 400;
dbHeight.Duration = dbWidth.Duration;
story.Children.Add(dbWidth);
Storyboard.SetTargetName(dbWidth, bMenu.Name);
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty));
story.Children.Add(dbHeight);
Storyboard.SetTargetName(dbHeight, bMenu.Name);
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty));
DoubleAnimation dbCanvasX = new DoubleAnimation();
dbCanvasX.From = 0;
dbCanvasX.To = 5;
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(2.25));
DoubleAnimation dbCanvasY = new DoubleAnimation();
dbCanvasY.From = 0;
dbCanvasY.To = 5;
dbCanvasY.Duration = dbCanvasX.Duration;
story.Children.Add(dbCanvasX);
Storyboard.SetTargetName(dbCanvasX, bMenu.Name);
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(dbCanvasY);
Storyboard.SetTargetName(dbCanvasY, bMenu.Name);
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty));
story.Begin(this);
}

}
}
}
}

}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
[/CODE]

  • 0

Sorry, at this point my advice is to put a break point in and see if the code is getting hit.

I can't see anything obvious >.<

EDIT:: I'd also start iterating children as of:


Grid grd = element as Grid;
foreach (UIElement mnuElement in grd.Children)
[/CODE]

Just in case there is some of odd "Typing" issue.

  • 0

I'm not entirely sure, but try changing story.Begin(this) to just story.Begin();

It shouldn't matter whether it's there at compile time or not - by the time you run the code it should already be in the visual tree at the correct position, so it should make no difference (although depending on the hardware and complexity of the menu, you may want to attach the storyboard creation to the loaded event of the UserControl, just to be safe and make sure it's properly in the visual tree)

  • 0
  On 13/01/2012 at 18:21, articuno1au said:

Sorry, at this point my advice is to put a break point in and see if the code is getting hit.

I can't see anything obvious >.<

EDIT:: I'd also start iterating children as of:


Grid grd = element as Grid;
foreach (UIElement mnuElement in grd.Children)
[/CODE]

Just in case there is some of odd "Typing" issue.

I step though the entire function, and it runs fine, finds the correct Menu, I have a titlebar menu already set, so the code correctly ignores that.

  On 13/01/2012 at 18:22, ~Johnny said:

I'm not entirely sure, but try changing story.Begin(this) to just story.Begin();

It shouldn't matter whether it's there at compile time or not - by the time you run the code it should already be in the visual tree at the correct position, so it should make no difference

I tried that, similar error; "No applicable name scope exists to resolve the name 'FirstMenu'."

The issue with compile time is that if I use

[CODE]
Storyboard.SetTargetName(dbCanvasX, this.BediaGrid.bmnuBediaMenu.Name);
[/CODE]

The code will not run/compile as the object "bmnuBediaMenu" does not exist within the grid. Or am I missing what you are trying to say?

Again, thank you both for your time. Happy Friday the 13th!

VS screams

  • 0

If the menu successfully gets added to the Grid without crashing (this is without the storyboard code), then everything should be fine. You are adding the menu to your grid in your code, so it will exist in the visual tree when you run the code.

For what it's worth I've used this code in my own projects to some success for animating across X axis (and applicable for Y)


/// <summary>
/// Slide animate a FrameworkElement along the X axis
/// </summary>
/// <param name="x">The FrameworkElement to animate</param>
/// <param name="df">Starting X offset of the animation</param>
/// <param name="dt">Ending X offset of the animation</param>
/// <param name="time">The length of the animation in milliseconds</param>
internal static void AnimateElementTransformX(FrameworkElement x, Double df, Double dt, Int32 time)
{
try
{
DoubleAnimation ani = new DoubleAnimation();
ani.From = (!(Double.IsNaN(df))) ? df : x.RenderTransform.Value.OffsetX;
ani.To = 0;
ani.Duration = new Duration(TimeSpan.FromMilliseconds(time));
var sb = new Storyboard();
sb.Children.Add(ani);
TranslateTransform tt2 = new TranslateTransform();
App.Current.MainWindow.RegisterName("TT2", tt2);
x.RenderTransform = tt2;
Storyboard.SetTargetName(ani, "TT2");
Storyboard.SetTargetProperty(ani, new PropertyPath(TranslateTransform.XProperty));
x.Resources.Add("SB);
sb.Begin();
x.Resources.Remove("SB");
App.Current.MainWindow.UnregisterName("TT2");
}
catch { /** Null Target Animation Error **/ }
}
[/CODE]

Which you'd use something like

[font=courier new,courier,monospace]AnimateElementTransformX(bmnuBediaMenu, 50, 0, 100);[/font]

for a 100ms animation, animating it from a 50px offset to it's original position

Though I'd probably find it easier to create the animation in XAML in the UserControl, and then set the animation to trigger when the UserControl is loaded.

  • 0

The menu adds to the canvas/grid fine... and I had tried a some code similar to yours (thanks!) but it still errors on sb.Begin() with: 'TT2' name cannot be found in the name scope of 'BediaMenu.BMenu'." I changed the bmnuBediaMenu.Name = "TT2" in the original code to insure that that was not the issue and yet....

I feel that the answer is really close, but I am missing it. (obviously)

  • 0

Ahh, I think I might have spotted it.

Is it that you are calling story.Begin(this) on LoadBediaMenu rather than LoadedBediaMenu (OnLoad/OnLoaded)?

I can't tell where you have registered the event, but that could do it I think >.<

  • 0
  On 13/01/2012 at 18:45, James Rose said:

The menu adds to the canvas/grid fine... and I had tried a some code similar to yours (thanks!) but it still errors on sb.Begin() with: 'TT2' name cannot be found in the name scope of 'BediaMenu.BMenu'." I changed the bmnuBediaMenu.Name = "TT2" in the original code to insure that that was not the issue and yet....

I feel that the answer is really close, but I am missing it. (obviously)

I *think* (I'm not sure, can't remember what I was thinking when I wrote it :p), but this *might* work for you.


/// <summary>
/// Slide animate a FrameworkElement along the X axis
/// </summary>
/// <param name="x">The FrameworkElement to animate</param>
/// <param name="df">Starting X offset of the animation</param>
/// <param name="dt">Ending X offset of the animation</param>
/// <param name="time">The length of the animation</param>
/// <param name="p">The parent element to register the transform in</param>
internal static void AnimateElementTransformX(FrameworkElement x, Double df, Double dt, Int32 time, FrameworkElement p)
{
try
{
DoubleAnimation ani = new DoubleAnimation();
ani.From = (!(Double.IsNaN(df))) ? df : x.RenderTransform.Value.OffsetX;
ani.To = 0;
ani.Duration = new Duration(TimeSpan.FromMilliseconds(time));
var sb = new Storyboard();
sb.Children.Add(ani);
TranslateTransform tt2 = new TranslateTransform();
p.RegisterName("TT2", tt2);
x.RenderTransform = tt2;
Storyboard.SetTargetName(ani, "TT2");
Storyboard.SetTargetProperty(ani, new PropertyPath(TranslateTransform.XProperty));
x.Resources.Add("SB);
sb.Begin();
x.Resources.Remove("SB");
p.UnregisterName("TT2");
}
catch { /** Null Target Animation Error **/ }
}
[/CODE]

The difference here is you also have to pass in the element's parent element at the end as well, so something like AnimateElementTransformX(bmnuBediaMenu, 50, 0, 100, BediaGrid) might work. Although for some reason I never actaully used this code over the previous method, so it may not actually work. (Again, I must prefer to write them in XAML)

  • 0

Johnny,

Thanks, and that was what I was attempting to do (had not gotten there yet, so thanks!) but still an error on sb.Begin

'TT2' name cannot be found in the name scope of 'BediaMenu.BMenu'.

-----------------

Art,

The function "LoadBediaMenu" adds one menu and then calls Johnny's function "AnimateElementTransformX" where the BediaMenu is to be moved. Is this an issue? Can't I add a control and then move it within the same function? (even though "technically" these are two functions)

  • 0

I think it's to do with the object not being fully initiated.

I was just working my way through: http://msdn.microsoft.com/en-us/library/ms752312.aspx

They've bound the animation separately from the animation start. This is (I think) irrelevant. The interesting thing to note is when the story.Begin(this) is called. I think you need to delay the Begin call until after the object is fully loaded.

I think the best part of my idea is all it "costs" is binding the start to Loaded rather than Load. 2 seconds to test, 2 seconds to undo >.<

  • 0
  On 13/01/2012 at 19:24, articuno1au said:

I think it's to do with the object not being fully initiated.

I was just working my way through: http://msdn.microsof...y/ms752312.aspx

They've bound the animation separately from the animation start. This is (I think) irrelevant. The interesting thing to note is when the story.Begin(this) is called. I think you need to delay the Begin call until after the object is fully loaded.

I think the best part of my idea is all it "costs" is binding the start to Loaded rather than Load. 2 seconds to test, 2 seconds to undo >.<

I believe you're taking about this piece from that link


private void myRectangleLoaded(object sender, RoutedEventArgs e)
{
myStoryboard.Begin(this);
}
[/CODE]

I have been reviewing that page for a few days and saw that. However it does not matter. For example I have this code that is called when I click on the Titlebar

[CODE]
private void Titlebar_MouseDown(object sender, MouseButtonEventArgs e)
{
if (bLoaded == false)
{
LoadBediaMenu("Fade In and Out 2", 500);
bLoaded = true;
}
else
{
AnimateElementTransformX(bmnuBediaMenu, 0, 30, 100, BediaGrid);
}
}
[/CODE]

The BediaMenu is completely loaded and yet I still get the same error: 'TT2' name cannot be found in the name scope of 'BediaMenu.BMenu'.

Very strange, very interesting.... and more than a bit annoying. One of my laws of development is that the longer it takes to find a solution to an issue, the more simple/straight-forward it is, and therefore the dumber you will feel when you figure it out. This one is going to make me feel REAL stupid, I just know it.

  • 0

I'd say skip all that, go with this in the XAML of the UserControl:


<Usercontrol ....
x:name="bmnuMenu"
...>
<UserControl.Resources>
<Storyboard x:Key="Entry">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="bmnuMenu">
<EasingDoubleKeyFrame KeyTime="0" Value="30"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<UserControl.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</UserControl.RenderTransform>
<UserControl.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Entry}"/>
</EventTrigger>
</UserControl.Triggers>[/CODE]

You probably don't need all those transform groups, but that should work.

Edit: Stupid thing has messed up the casings.

  • 0
  On 13/01/2012 at 19:42, ~Johnny said:

I'd say skip all that, go with this in the XAML of the UserControl:


<usercontrol ....="" x:name="UserControl">
<usercontrol.resources>
<storyboard x:key="Entry">
<doubleanimationusingkeyframes storyboard.targetproperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" storyboard.targetname="UserControl">
<easingdoublekeyframe keytime="0" value="30">
<easingdoublekeyframe keytime="0:0:0.3" value="0">
</easingdoublekeyframe></easingdoublekeyframe></doubleanimationusingkeyframes>
</storyboard>
</usercontrol.resources>
<usercontrol.rendertransform>
<transformgroup>
<scaletransform>
<skewtransform>
<rotatetransform>
<translatetransform>
</translatetransform></rotatetransform></skewtransform></scaletransform></transformgroup>
</usercontrol.rendertransform>
<usercontrol.triggers>
<eventtrigger routedevent="FrameworkElement.Loaded">
<beginstoryboard storyboard="{StaticResource Entry}">
</beginstoryboard></eventtrigger>
</usercontrol.triggers>
[/CODE]

You probably don't need all those transform groups, but that should work.

I'd love to just use XAML, but the number of menus varies based on the user's screen height and the height of the menu (customizable) so until runtime I do not know how many I will need. I REALLY wish I could know ahead of time, that would make my life SO much easier.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Does it mean that the game will have weapons now? If that is the case, I'm interested. Not having weapons does not make any sense, even if it changes the gameplay. In such a hostile environment the first thing anyone would do is get as much weapons as they could.
    • This DDR5-6400 CL36 32GB RGB RAM that supports both AMD and Intel is only $72 by Sayan Sen Recently, we covered several SSD deals, both internal and external. These include the Crucial X9 Pro and X10 Pro, the P310 2280, and the Samsung 990 EVO Plus. Meanwhile if you are looking for RAM to upgrade your desktop PC or build a new one, the PNY XLR8 Gaming EPIC-X RGB DDR5-6400 Kit can be your go-to choice as it is currently just $72 (purchase link down below). In terms of specs, this dual-RAM kit delivers 32GB of total DDR5 capacity (each module is 16GB) running at 3200 Hz to deliver 6400 MT/s (PC5-51200) at 1.4 volts. Pre-programmed Intel XMP 3.0 and AMD EXPO memory overclocking preset profiles mean you can fire up the kit to its rated speed with a simple BIOS tweak, rather than having to deal with manual timing adjustments. The CAS latency for this DDR5-6400 kit is 36, which is quite tight for a preset profile. Thermal performance is said to be stellar thanks to the aluminum heat spreader, which should help dissipate heat during extended gaming sessions. Additionally, the heat spreader is also said to feature an "embossed pennant design that enhances the overall look and complements the lighting of other components." Speaking of lighting, the included EPIC-X RGB model features ARGB LEDs diffused through a geometric polymer light pipe and allows syncing via Asus Aura Sync, Gigabyte RGB Fusion, MSI Mystic Light, or ASRock Polychrome Sync software. Get the PNY RAM at the link below: PNY XLR8 Gaming Epic-X RGB™ 32GB (2x16GB) DDR5 RAM 6400 CL36-48-48-104 Desktop Memory Kit (MD32GK2D5640036XRGB): $72.24 (Sold and Shipped by Amazon US) (MSRP: $109.99) This Amazon deal is US-specific and not available in other regions unless specified. If you don't like it or want to look at more options, check out the Amazon US deals page here. Get Prime (SNAP), Prime Video, Audible Plus or Kindle / Music Unlimited. Free for 30 days. As an Amazon Associate, we earn from qualifying purchases.
    • Vivaldi 7.5 is out with colorful tab stacks, improved tab menu, and more by Taras Buria Vivaldi Technologies has released a new feature update for the Vivaldi browser. Version 7.5 is now available with some much-requested features by the community, privacy improvements, bug fixes, and other changes. The release is not the biggest one, but it still packs useful changes, such as colorful tab stacks, a reworked tab context menu, and multiple improvements under the hood: Vivaldi now supports colorful Tab Stacks. This feature groups related tabs and helps you keep everything well-organized. Now, besides giving your stacks names, you can assign colors, which makes it easier to find the stack you need. Developers also added a new dialog: right-click a stack, click "Edit Stack," and give it a new name or choose a color. The browser also received a cleaner and better-organized tab context menu. Vivaldi says the new version is more intuitive and easier to use. Another important change is the ability to define a custom DNS provider with support for DNS over HTTPS. Finally, here are some of the under-the-hood improvements in Vivaldi 7.5: Address Bar: Fixed focus weirdness, suggestion hiccups, and dropdown quirks Ad Blocker: Now supports badfilter, strict3p, and strict1p rules Bookmarks & Notes: Better drag-and-drop, with clearer visual feedback Mail & Calendar: Smarter threading, invite handling, and polish throughout Dashboard & Widgets: Layout tweaks, transparency improvements, drag-and-drop goodness Quick Commands: Now shows synced tabs and handles errors more gracefully Settings: UI improvements across the board, from DNS input to workspace rules visibility You can find the complete changelog for Vivaldi 7.5 in a blog post on the official website. If you want to try this highly customizable browser, download it using this link.
    • "While users may say they do not want their data used for personalized ads, Meta believes that without personalization, user experience declines with an almost 800% rise in ads being marked as “irrelevant” or “repetitive”. The ads might be more irrelevant, but it's not like people crave ads in the first place. My user experience with ads isn't better with personalization, because I don't want them there to begin with. So I might as well have non-personalized ads if I am gonna have ads, because then I at least get tracked less, and that makes it a better user experience for me.
    • The fact that they didn't offer a non-personalized ad-supported option, when they were mandated by law, was the final nail in the coffin in my case.
  • Recent Achievements

    • First Post
      loose_observer earned a badge
      First Post
    • Week One Done
      BeeJay_Balu earned a badge
      Week One Done
    • Week One Done
      filminutz earned a badge
      Week One Done
    • Reacting Well
      SteveJaye earned a badge
      Reacting Well
    • One Month Later
      MadMung0 earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      446
    2. 2
      ATLien_0
      161
    3. 3
      +FloatingFatMan
      147
    4. 4
      Nick H.
      65
    5. 5
      +thexfile
      62
  • Tell a friend

    Love Neowin? Tell a friend!